diff --git a/DDrawCompat/DDraw/RealPrimarySurface.cpp b/DDrawCompat/DDraw/RealPrimarySurface.cpp index 5e97de1..c5076bd 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.cpp +++ b/DDrawCompat/DDraw/RealPrimarySurface.cpp @@ -38,6 +38,9 @@ namespace void onRelease(); + CompatWeakPtr g_defaultPrimaryDD; + CompatWeakPtr g_defaultPrimary; + CompatWeakPtr g_frontBuffer; CompatWeakPtr g_windowedBackBuffer; CompatWeakPtr g_clipper; @@ -100,6 +103,65 @@ namespace } } + BOOL WINAPI createDefaultPrimaryEnum( + GUID* lpGUID, LPSTR /*lpDriverDescription*/, LPSTR lpDriverName, LPVOID lpContext, HMONITOR /*hm*/) + { + auto& deviceName = *static_cast(lpContext); + if (deviceName != std::wstring(lpDriverName, lpDriverName + strlen(lpDriverName))) + { + return TRUE; + } + + CompatPtr dd; + if (FAILED(CALL_ORIG_PROC(DirectDrawCreateEx)( + lpGUID, reinterpret_cast(&dd.getRef()), IID_IDirectDraw7, nullptr))) + { + return FALSE; + } + + if (FAILED(dd.get()->lpVtbl->SetCooperativeLevel(dd, nullptr, DDSCL_NORMAL))) + { + return FALSE; + } + + CompatPtr 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() + { + if (g_frontBuffer || g_defaultPrimary && SUCCEEDED(g_defaultPrimary->IsLost(g_defaultPrimary))) + { + return; + } + + DDraw::RealPrimarySurface::destroyDefaultPrimary(); + + if (DDraw::TagSurface::doesFullscreenDirectDrawExist()) + { + return; + } + + auto dm = Win32::DisplayMode::getEmulatedDisplayMode(); + if (0 == dm.diff.cx && 0 == dm.diff.cy) + { + return; + } + + CALL_ORIG_PROC(DirectDrawEnumerateExA)(createDefaultPrimaryEnum, &dm.deviceName, DDENUM_ATTACHEDSECONDARYDEVICES); + } + CompatPtr createWindowedBackBuffer(DDRAWI_DIRECTDRAW_LCL* ddLcl, DWORD width, DWORD height) { if (!ddLcl) @@ -361,6 +423,7 @@ namespace } DDraw::ScopedThreadLock lock; + createDefaultPrimary(); updatePresentationWindowPos(); msUntilUpdateReady = DDraw::RealPrimarySurface::flush(); } @@ -372,6 +435,7 @@ namespace DDraw template HRESULT RealPrimarySurface::create(CompatRef dd) { + LOG_FUNC("RealPrimarySurface::create", &dd); DDraw::ScopedThreadLock lock; g_monitorRect = D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr::from(&dd)).monitorInfo.rcMonitor; @@ -439,6 +503,12 @@ namespace DDraw template HRESULT RealPrimarySurface::create(CompatRef); template HRESULT RealPrimarySurface::create(CompatRef); + void RealPrimarySurface::destroyDefaultPrimary() + { + g_defaultPrimary.release(); + g_defaultPrimaryDD.release(); + } + HRESULT RealPrimarySurface::flip(CompatPtr surfaceTargetOverride, DWORD flags) { const DWORD flipInterval = getFlipInterval(flags); diff --git a/DDrawCompat/DDraw/RealPrimarySurface.h b/DDrawCompat/DDraw/RealPrimarySurface.h index 9469bd8..ba0e83d 100644 --- a/DDrawCompat/DDraw/RealPrimarySurface.h +++ b/DDrawCompat/DDraw/RealPrimarySurface.h @@ -15,6 +15,7 @@ namespace DDraw template static HRESULT create(CompatRef dd); + static void destroyDefaultPrimary(); static HRESULT flip(CompatPtr surfaceTargetOverride, DWORD flags); static int flush(); static HWND getDevicePresentationWindow(); diff --git a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp index 4b4729d..70fd6b1 100644 --- a/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/PrimarySurface.cpp @@ -50,6 +50,8 @@ namespace DDraw template HRESULT PrimarySurface::create(CompatRef dd, TSurfaceDesc desc, TSurface*& surface) { + LOG_FUNC("PrimarySurface::create", &dd, desc, surface); + DDraw::RealPrimarySurface::destroyDefaultPrimary(); const auto& dm = DDraw::DirectDraw::getDisplayMode(*CompatPtr::from(&dd)); g_monitorRect = D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr::from(&dd)).monitorInfo.rcMonitor; g_monitorRect.right = g_monitorRect.left + dm.dwWidth; @@ -58,7 +60,7 @@ namespace DDraw HRESULT result = RealPrimarySurface::create(dd); if (FAILED(result)) { - return result; + return LOG_RESULT(result); } const DWORD origCaps = desc.ddsCaps.dwCaps; @@ -79,7 +81,7 @@ namespace DDraw LOG_INFO << "ERROR: Failed to create the compat primary surface: " << Compat::hex(result); g_monitorRect = {}; RealPrimarySurface::release(); - return result; + return LOG_RESULT(result); } g_origCaps = origCaps; @@ -97,7 +99,7 @@ namespace DDraw g_device = D3dDdi::Device::findDeviceByResource(DirectDrawSurface::getDriverResourceHandle(*surface)); data->restore(); D3dDdi::Device::updateAllConfig(); - return DD_OK; + return LOG_RESULT(DD_OK); } template HRESULT PrimarySurface::create( diff --git a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp index 41866d2..f2f06bc 100644 --- a/DDrawCompat/DDraw/Surfaces/TagSurface.cpp +++ b/DDrawCompat/DDraw/Surfaces/TagSurface.cpp @@ -43,6 +43,18 @@ namespace DDraw 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) { for (auto& pair : g_ddObjects) diff --git a/DDrawCompat/DDraw/Surfaces/TagSurface.h b/DDrawCompat/DDraw/Surfaces/TagSurface.h index b8a4169..1e42b6d 100644 --- a/DDrawCompat/DDraw/Surfaces/TagSurface.h +++ b/DDrawCompat/DDraw/Surfaces/TagSurface.h @@ -19,6 +19,7 @@ namespace DDraw static TagSurface* get(CompatRef dd); static TagSurface* findFullscreenWindow(HWND hwnd); + static bool doesFullscreenDirectDrawExist(); static void forEachDirectDraw(std::function)> callback); void setFullscreenWindow(HWND hwnd);