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

Create default primary in fullscreen mode

Fixes intro videos displaying in a small window in Midtown Madness 2
This commit is contained in:
narzoul 2022-07-23 23:56:08 +02:00
parent 2099c80095
commit 6327bc506f
5 changed files with 80 additions and 52 deletions

View File

@ -39,7 +39,6 @@ namespace
void onRelease(); void onRelease();
CompatWeakPtr<IDirectDraw7> g_defaultPrimaryDD;
CompatWeakPtr<IDirectDrawSurface7> g_defaultPrimary; CompatWeakPtr<IDirectDrawSurface7> g_defaultPrimary;
CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer; CompatWeakPtr<IDirectDrawSurface7> g_frontBuffer;
@ -113,47 +112,54 @@ namespace
return TRUE; return TRUE;
} }
CompatPtr<IDirectDraw7> dd; auto tagSurface = DDraw::TagSurface::findFullscreenWindow();
if (FAILED(CALL_ORIG_PROC(DirectDrawCreateEx)( LOG_DEBUG << "Creating " << (tagSurface ? "fullscreen" : "windowed") << " default primary";
lpGUID, reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr)))
if (tagSurface)
{ {
return FALSE; DDSURFACEDESC desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
CompatPtr<IDirectDraw> dd(tagSurface->getDD());
CompatPtr<IDirectDrawSurface> primary;
dd.get()->lpVtbl->CreateSurface(dd, &desc, &primary.getRef(), nullptr);
g_defaultPrimary = CompatPtr<IDirectDrawSurface7>(primary).detach();
}
else
{
CompatPtr<IDirectDraw7> dd;
if (FAILED(CALL_ORIG_PROC(DirectDrawCreateEx)(
lpGUID, reinterpret_cast<void**>(&dd.getRef()), IID_IDirectDraw7, nullptr)))
{
return FALSE;
}
if (FAILED(dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL)))
{
return FALSE;
}
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
dd.get()->lpVtbl->CreateSurface(dd, &desc, &g_defaultPrimary.getRef(), nullptr);
} }
if (FAILED(dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL))) return nullptr != g_defaultPrimary;
{
return FALSE;
}
CompatPtr<IDirectDrawSurface7> primary;
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_CAPS;
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
if (FAILED(dd.get()->lpVtbl->CreateSurface(dd, &desc, &primary.getRef(), nullptr)))
{
return FALSE;
}
g_defaultPrimary = primary.detach();
g_defaultPrimaryDD = dd.detach();
return FALSE;
} }
void createDefaultPrimary() void createDefaultPrimary()
{ {
if (g_frontBuffer || g_defaultPrimary && SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary))) if (g_defaultPrimary ? SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary)) : g_frontBuffer)
{ {
return; return;
} }
DDraw::RealPrimarySurface::destroyDefaultPrimary(); DDraw::RealPrimarySurface::destroyDefaultPrimary();
if (DDraw::TagSurface::doesFullscreenDirectDrawExist())
{
return;
}
auto dm = Win32::DisplayMode::getEmulatedDisplayMode(); auto dm = Win32::DisplayMode::getEmulatedDisplayMode();
if (0 == dm.diff.cx && 0 == dm.diff.cy) if (0 == dm.diff.cx && 0 == dm.diff.cy)
{ {
@ -270,6 +276,7 @@ namespace
g_presentationWindow = nullptr; g_presentationWindow = nullptr;
} }
g_defaultPrimary = nullptr;
g_frontBuffer = nullptr; g_frontBuffer = nullptr;
g_lastFlipSurface = nullptr; g_lastFlipSurface = nullptr;
g_windowedBackBuffer.release(); g_windowedBackBuffer.release();
@ -425,8 +432,6 @@ namespace
} }
DDraw::ScopedThreadLock lock; DDraw::ScopedThreadLock lock;
createDefaultPrimary();
updatePresentationWindowPos();
msUntilUpdateReady = DDraw::RealPrimarySurface::flush(); msUntilUpdateReady = DDraw::RealPrimarySurface::flush();
} }
} }
@ -509,8 +514,11 @@ namespace DDraw
void RealPrimarySurface::destroyDefaultPrimary() void RealPrimarySurface::destroyDefaultPrimary()
{ {
g_defaultPrimary.release(); if (g_defaultPrimary)
g_defaultPrimaryDD.release(); {
LOG_DEBUG << "Destroying default primary";
g_defaultPrimary.release();
}
} }
HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags) HRESULT RealPrimarySurface::flip(CompatPtr<IDirectDrawSurface7> surfaceTargetOverride, DWORD flags)
@ -585,6 +593,9 @@ namespace DDraw
} }
} }
createDefaultPrimary();
updatePresentationWindowPos();
auto src(g_isDelayedFlipPending ? g_lastFlipSurface->getDDS() : DDraw::PrimarySurface::getPrimary()); auto src(g_isDelayedFlipPending ? g_lastFlipSurface->getDDS() : DDraw::PrimarySurface::getPrimary());
RECT emptyRect = {}; RECT emptyRect = {};
HRESULT result = src ? src->BltFast(src, 0, 0, src, &emptyRect, DDBLTFAST_WAIT) : DD_OK; HRESULT result = src ? src->BltFast(src, 0, 0, src, &emptyRect, DDBLTFAST_WAIT) : DD_OK;

View File

@ -13,17 +13,20 @@ namespace DDraw
{ {
TagSurface::TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl) TagSurface::TagSurface(DWORD origCaps, DDRAWI_DIRECTDRAW_LCL* ddLcl)
: Surface(origCaps) : Surface(origCaps)
, m_ddLcl(ddLcl) , m_ddInt{}
, m_fullscreenWindow(nullptr) , m_fullscreenWindow(nullptr)
, m_fullscreenWindowStyle(0) , m_fullscreenWindowStyle(0)
, m_fullscreenWindowExStyle(0) , m_fullscreenWindowExStyle(0)
{ {
m_ddInt.lpVtbl = &CompatVtable<IDirectDraw>::s_origVtable;
m_ddInt.lpLcl = ddLcl;
m_ddInt.dwIntRefCnt = 1;
} }
TagSurface::~TagSurface() TagSurface::~TagSurface()
{ {
setFullscreenWindow(nullptr); setFullscreenWindow(nullptr);
g_ddObjects.erase(m_ddLcl); g_ddObjects.erase(m_ddInt.lpLcl);
} }
HRESULT TagSurface::create(CompatRef<IDirectDraw> dd) HRESULT TagSurface::create(CompatRef<IDirectDraw> dd)
@ -43,23 +46,12 @@ namespace DDraw
return Surface::create(dd, desc, surface, std::move(privateData)); return Surface::create(dd, desc, surface, std::move(privateData));
} }
bool TagSurface::doesFullscreenDirectDrawExist()
{
for (auto& pair : g_ddObjects)
{
if (pair.second->m_fullscreenWindow)
{
return true;
}
}
return false;
}
TagSurface* TagSurface::findFullscreenWindow(HWND hwnd) TagSurface* TagSurface::findFullscreenWindow(HWND hwnd)
{ {
for (auto& pair : g_ddObjects) for (auto& pair : g_ddObjects)
{ {
if (hwnd == pair.second->m_fullscreenWindow) if (pair.second->m_fullscreenWindow &&
(!hwnd || hwnd == pair.second->m_fullscreenWindow))
{ {
return pair.second; return pair.second;
} }
@ -93,6 +85,11 @@ namespace DDraw
return g_ddObjects[ddLcl]; return g_ddObjects[ddLcl];
} }
CompatPtr<IDirectDraw7> TagSurface::getDD()
{
return CompatPtr<IDirectDraw7>::from(reinterpret_cast<IDirectDraw*>(&m_ddInt));
}
void TagSurface::setFullscreenWindow(HWND hwnd) void TagSurface::setFullscreenWindow(HWND hwnd)
{ {
if (m_fullscreenWindow == hwnd) if (m_fullscreenWindow == hwnd)

View File

@ -16,10 +16,9 @@ namespace DDraw
static TagSurface* get(DDRAWI_DIRECTDRAW_LCL* ddLcl); static TagSurface* get(DDRAWI_DIRECTDRAW_LCL* ddLcl);
static TagSurface* get(CompatRef<IDirectDraw> dd); static TagSurface* get(CompatRef<IDirectDraw> dd);
static TagSurface* findFullscreenWindow(HWND hwnd); static TagSurface* findFullscreenWindow(HWND hwnd = nullptr);
static bool doesFullscreenDirectDrawExist();
CompatPtr<IDirectDraw7> getDD();
bool isFullscreen() const { return m_fullscreenWindow; } bool isFullscreen() const { return m_fullscreenWindow; }
void setFullscreenWindow(HWND hwnd); void setFullscreenWindow(HWND hwnd);
LONG setWindowStyle(LONG style); LONG setWindowStyle(LONG style);
@ -28,7 +27,7 @@ namespace DDraw
private: private:
static HRESULT create(CompatRef<IDirectDraw> dd); static HRESULT create(CompatRef<IDirectDraw> dd);
DDRAWI_DIRECTDRAW_LCL* m_ddLcl; DDRAWI_DIRECTDRAW_INT m_ddInt;
HWND m_fullscreenWindow; HWND m_fullscreenWindow;
LONG m_fullscreenWindowStyle; LONG m_fullscreenWindowStyle;
LONG m_fullscreenWindowExStyle; LONG m_fullscreenWindowExStyle;

View File

@ -14,6 +14,10 @@
namespace namespace
{ {
typedef void (WINAPI* SurfaceFlipNotifyFunc)(void*);
SurfaceFlipNotifyFunc g_origSurfaceFlipNotify = nullptr;
SurfaceFlipNotifyFunc g_origSurfaceFlipNotify7 = nullptr;
void hookDirect3dDevice(CompatRef<IDirect3D3> d3d, CompatRef<IDirectDrawSurface4> renderTarget); void hookDirect3dDevice(CompatRef<IDirect3D3> d3d, CompatRef<IDirectDrawSurface4> renderTarget);
void hookDirect3dExecuteBuffer(CompatRef<IDirect3DDevice> dev); void hookDirect3dExecuteBuffer(CompatRef<IDirect3DDevice> dev);
void hookDirect3dLight(CompatRef<IDirect3D3> d3d); void hookDirect3dLight(CompatRef<IDirect3D3> d3d);
@ -220,6 +224,16 @@ namespace
Direct3d::Direct3dViewport::hookVtable(*CompatPtr<IDirect3DViewport2>(viewport).get()->lpVtbl); Direct3d::Direct3dViewport::hookVtable(*CompatPtr<IDirect3DViewport2>(viewport).get()->lpVtbl);
Direct3d::Direct3dViewport::hookVtable(*CompatPtr<IDirect3DViewport3>(viewport).get()->lpVtbl); Direct3d::Direct3dViewport::hookVtable(*CompatPtr<IDirect3DViewport3>(viewport).get()->lpVtbl);
} }
template <auto& origSurfaceFlipNotify>
void WINAPI surfaceFlipNotify(void* ptr)
{
LOG_FUNC("SurfaceFlipNotify", ptr);
if (ptr)
{
origSurfaceFlipNotify(ptr);
}
}
} }
namespace Direct3d namespace Direct3d
@ -233,5 +247,10 @@ namespace Direct3d
hookDirect3d(*dd, *renderTarget4); hookDirect3d(*dd, *renderTarget4);
hookDirect3d7(*dd7); hookDirect3d7(*dd7);
} }
Compat::hookFunction("d3dim", "SurfaceFlipNotify", reinterpret_cast<void*&>(g_origSurfaceFlipNotify),
surfaceFlipNotify<g_origSurfaceFlipNotify>);
Compat::hookFunction("d3dim700", "SurfaceFlipNotify", reinterpret_cast<void*&>(g_origSurfaceFlipNotify7),
surfaceFlipNotify<g_origSurfaceFlipNotify7>);
} }
} }

View File

@ -180,6 +180,7 @@ namespace Gdi
void setEmulated(bool isEmulated) void setEmulated(bool isEmulated)
{ {
LOG_FUNC("Cursor::setEmulated", isEmulated);
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedCriticalSection lock(g_cs);
if (isEmulated == g_isEmulated) if (isEmulated == g_isEmulated)
{ {
@ -202,6 +203,7 @@ namespace Gdi
void setMonitorClipRect(const RECT& rect) void setMonitorClipRect(const RECT& rect)
{ {
LOG_FUNC("Cursor::setMonitorClipRect", rect);
Compat::ScopedCriticalSection lock(g_cs); Compat::ScopedCriticalSection lock(g_cs);
if (IsRectEmpty(&rect)) if (IsRectEmpty(&rect))
{ {