Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 39 additions & 11 deletions src/d3d11/d3d11_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@
#include <cfloat>
#include <format>

#define MACDRV_ESCAPE_GET_SURFACE 6790
#define MACDRV_ESCAPE_RELEASE_SURFACE 6791

struct macdrv_escape_surface
{
UINT64 surface; /* Opaque pointer to struct macdrv_client_surface */
UINT64 layer; /* Opaque pointer to CAMetalLayer */
};

/**
Ref: https://learn.microsoft.com/en-us/windows/win32/api/dxgi1_3/nf-dxgi1_3-idxgiswapchain2-setmaximumframelatency
This value is 1 by default.
Expand Down Expand Up @@ -131,10 +140,26 @@ class MTLD3D11SwapChain final : public MTLDXGISubObject<IDXGISwapChain4, MTLD3D1
monitor_(wsi::getWindowMonitor(hWnd)),
hud(WMT::DeveloperHUDProperties::instance()) {

native_view_ = WMT::CreateMetalViewFromHWND((intptr_t)hWnd, pDevice->GetMTLDevice(), layer_weak_);
HDC hdc = GetDC(hWnd);
int escapeCode = MACDRV_ESCAPE_GET_SURFACE;
int supported = ExtEscape(hdc, QUERYESCSUPPORT, sizeof(int), (LPCSTR)&escapeCode, 0, NULL);
if (supported > 0) {
struct macdrv_escape_surface surfaceInfo = {0};
int result = ExtEscape(hdc, MACDRV_ESCAPE_GET_SURFACE, 0, NULL, sizeof(surfaceInfo), (LPSTR)&surfaceInfo);
if (result > 0 && surfaceInfo.layer) {
client_surface_.handle = surfaceInfo.surface;
layer_weak_.handle = surfaceInfo.layer;
}
}
ReleaseDC(hWnd, hdc);

if (!layer_weak_) {
ERR("Failed to get metal layer via MACDRV_ESCAPE_GET_SURFACE.");
native_view_ = WMT::CreateMetalViewFromHWND((intptr_t)hWnd, pDevice->GetMTLDevice(), layer_weak_);
}

if (!native_view_) {
ERR("Failed to create metal view, it seems like your Wine has no exported symbols needed by DXMT.");
if (!layer_weak_) {
ERR("Failed to get metal layer, it seems like your Wine has not the needed functionality for DXMT.");
abort();
}

Expand Down Expand Up @@ -206,7 +231,16 @@ class MTLD3D11SwapChain final : public MTLDXGISubObject<IDXGISwapChain4, MTLD3D1

~MTLD3D11SwapChain() {
device_context_->WaitUntilGPUIdle();
WMT::ReleaseMetalView(native_view_);
if (client_surface_ != nullptr) {
HDC hdc = GetDC(hWnd);
struct macdrv_escape_surface surfaceInfo = {0};
surfaceInfo.surface = client_surface_.handle;
ExtEscape(hdc, MACDRV_ESCAPE_RELEASE_SURFACE, sizeof(surfaceInfo), (LPCSTR)&surfaceInfo, 0, NULL);
ReleaseDC(hWnd, hdc);
} else {
WMT::ReleaseMetalView(native_view_);
}
client_surface_ = {};
native_view_ = {};
CloseHandle(present_semaphore_);
};
Expand Down Expand Up @@ -1056,6 +1090,7 @@ class MTLD3D11SwapChain final : public MTLDXGISubObject<IDXGISwapChain4, MTLD3D1
Com<IDXGIFactory1> factory_;
Com<IMTLDXGIDevice> dxgi_device_;
WMT::Object native_view_;
WMT::Object client_surface_;
WMT::MetalLayer layer_weak_;
ULONG presentation_count_;
DXGI_SWAP_CHAIN_DESC1 desc_;
Expand Down Expand Up @@ -1096,13 +1131,6 @@ CreateSwapChain(
return DXGI_ERROR_INVALID_CALL;
InitReturnPtr(ppSwapChain);

DWORD window_process_id;
GetWindowThreadProcessId(hWnd, &window_process_id);
if (GetProcessId(GetCurrentProcess()) != window_process_id) {
ERR("CreateSwapChain: cross-process swapchain not supported yet");
return E_FAIL;
}

Com<IMTLDXGIDevice> layer_factory;
if (FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&layer_factory)))) {
ERR("CreateSwapChain: failed to get IMTLDXGIDevice");
Expand Down
17 changes: 17 additions & 0 deletions src/util/util_win32_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ inline BOOL DuplicateHandle(HANDLE hSourceProcessHandle,
return FALSE;
}

#define QUERYESCSUPPORT 8

inline HDC GetDC(HWND hWnd) {
dxmt::Logger::warn("GetDC not implemented.");
return nullptr;
}

inline int ReleaseDC(HWND hWnd, HDC hDC) {
dxmt::Logger::warn("ReleaseDC not implemented.");
return 0;
}

inline int ExtEscape(HDC hdc, int nEscape, int cbInput, LPCSTR lpszInData, int cbOutput, LPSTR lpszOutData) {
dxmt::Logger::warn("ExtEscape not implemented.");
return 0;
}


#define ARRAYSIZE(a) (sizeof(a)/sizeof(*(a)))

Expand Down
Loading