mirror of https://github.com/doitsujin/dxvk
Merge e4e89db23c
into ab715a8876
This commit is contained in:
commit
a3be9f7672
|
@ -183,6 +183,8 @@ namespace dxvk {
|
||||||
m_activeRTsWhichAreTextures = 0;
|
m_activeRTsWhichAreTextures = 0;
|
||||||
m_alphaSwizzleRTs = 0;
|
m_alphaSwizzleRTs = 0;
|
||||||
m_lastHazardsRT = 0;
|
m_lastHazardsRT = 0;
|
||||||
|
|
||||||
|
m_gamescopeWSI = dxvk::env::getEnvVar("ENABLE_GAMESCOPE_WSI") == "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1093,6 +1095,12 @@ namespace dxvk {
|
||||||
if (unlikely(iSwapChain != 0))
|
if (unlikely(iSwapChain != 0))
|
||||||
return D3DERR_INVALIDCALL;
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!IsGamescopeWSIEnabled()) {
|
||||||
|
return D3D9SwapChainEx::GetFrontBufferDataGDI(pDestSurface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
D3D9DeviceLock lock = LockDevice();
|
D3D9DeviceLock lock = LockDevice();
|
||||||
|
|
||||||
// In windowed mode, GetFrontBufferData takes a screenshot of the entire screen.
|
// In windowed mode, GetFrontBufferData takes a screenshot of the entire screen.
|
||||||
|
|
|
@ -1273,6 +1273,10 @@ namespace dxvk {
|
||||||
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
m_mostRecentlyUsedSwapchain = m_implicitSwapchain.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsGamescopeWSIEnabled() const {
|
||||||
|
return m_gamescopeWSI;
|
||||||
|
}
|
||||||
|
|
||||||
Com<D3D9InterfaceEx> m_parent;
|
Com<D3D9InterfaceEx> m_parent;
|
||||||
D3DDEVTYPE m_deviceType;
|
D3DDEVTYPE m_deviceType;
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
@ -1439,6 +1443,8 @@ namespace dxvk {
|
||||||
|
|
||||||
D3D9SwapChainEx* m_mostRecentlyUsedSwapchain = nullptr;
|
D3D9SwapChainEx* m_mostRecentlyUsedSwapchain = nullptr;
|
||||||
|
|
||||||
|
bool m_gamescopeWSI;
|
||||||
|
|
||||||
#ifdef D3D9_ALLOW_UNMAPPING
|
#ifdef D3D9_ALLOW_UNMAPPING
|
||||||
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
lru_list<D3D9CommonTexture*> m_mappedTextures;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -241,9 +241,91 @@ namespace dxvk {
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT D3D9SwapChainEx::GetFrontBufferDataGDI(IDirect3DSurface9* pDestSurface) {
|
||||||
|
D3D9Surface* dst = static_cast<D3D9Surface*>(pDestSurface);
|
||||||
|
|
||||||
|
if (unlikely(dst == nullptr))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
D3D9CommonTexture* dstTexInfo = dst->GetCommonTexture();
|
||||||
|
VkExtent3D dstTexExtent = dstTexInfo->GetExtentMip(dst->GetMipLevel());
|
||||||
|
|
||||||
|
if (unlikely(dstTexInfo->Desc()->Format != D3D9Format::A8R8G8B8)) {
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(dstTexInfo->Desc()->Pool != D3DPOOL_SYSTEMMEM && dstTexInfo->Desc()->Pool != D3DPOOL_SCRATCH))
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
|
||||||
|
const POINT ptZero = { 0, 0 };
|
||||||
|
HMONITOR primaryMonitor = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
|
||||||
|
MONITORINFO monitorInfo = {};
|
||||||
|
monitorInfo.cbSize = sizeof(MONITORINFO);
|
||||||
|
if (!GetMonitorInfo(primaryMonitor, &monitorInfo)) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to query window size.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
VkExtent2D monitorExtent = { uint32_t(monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left), uint32_t(monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top) };
|
||||||
|
VkExtent2D blitRegionExtent = { std::min(monitorExtent.width, dstTexExtent.width), std::min(monitorExtent.height, dstTexExtent.height) };
|
||||||
|
|
||||||
|
HDC srcDC = GetDC(nullptr);
|
||||||
|
HDC dstDC = CreateCompatibleDC(nullptr);
|
||||||
|
HBITMAP hbitmap = CreateCompatibleBitmap(srcDC, dstTexExtent.width, dstTexExtent.height);
|
||||||
|
|
||||||
|
if (unlikely(hbitmap == nullptr)) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to create bitmap.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP oldBitmap = static_cast<HBITMAP>(SelectObject(dstDC, hbitmap));
|
||||||
|
if (unlikely(oldBitmap == nullptr)) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to select bitmap for DC.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We always want the primary monitor which conveniently always sits at 0,0.
|
||||||
|
if (unlikely(!BitBlt(dstDC, 0, 0, blitRegionExtent.width, blitRegionExtent.height, srcDC, 0, 0, SRCCOPY))) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to create blit window.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
D3DLOCKED_RECT lockedRect = {};
|
||||||
|
if (unlikely(pDestSurface->LockRect(&lockedRect, nullptr, D3DLOCK_DISCARD) != D3D_OK)) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to lock dst surface.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BITMAPINFO info = {
|
||||||
|
sizeof(BITMAPINFOHEADER), int32_t(dstTexExtent.width), int32_t(-blitRegionExtent.height), 1, 32, BI_RGB, 0, 0, 0, 0, 0,
|
||||||
|
0,0,0,0
|
||||||
|
};
|
||||||
|
|
||||||
|
// For uncompressed RGB formats, the minimum stride is always the image width in bytes, rounded up to the nearest DWORD
|
||||||
|
// Our pitch is always aligned to 4 and GetFrontBufferData only supports A8R8G8B8. So we can avoid another copy to repack the data.
|
||||||
|
|
||||||
|
uint32_t lines = uint32_t(blitRegionExtent.height);
|
||||||
|
int scanlinesCopied = GetDIBits(dstDC, hbitmap, 0, lines, lockedRect.pBits, &info, DIB_RGB_COLORS);
|
||||||
|
if (unlikely(scanlinesCopied != int32_t(lines))) {
|
||||||
|
Logger::err("D3D9SwapChainEx::GetFrontBufferData: Failed to read hbitmap data.");
|
||||||
|
return D3DERR_INVALIDCALL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pDestSurface->UnlockRect();
|
||||||
|
|
||||||
|
SelectObject(dstDC, oldBitmap);
|
||||||
|
return D3D_OK;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) {
|
HRESULT STDMETHODCALLTYPE D3D9SwapChainEx::GetFrontBufferData(IDirect3DSurface9* pDestSurface) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!m_parent->IsGamescopeWSIEnabled() && (m_presentParams.Windowed || !HasFrontBuffer())) {
|
||||||
|
return D3D9SwapChainEx::GetFrontBufferDataGDI(pDestSurface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
D3D9DeviceLock lock = m_parent->LockDevice();
|
D3D9DeviceLock lock = m_parent->LockDevice();
|
||||||
|
|
||||||
// This function can do absolutely everything!
|
// This function can do absolutely everything!
|
||||||
|
|
|
@ -134,6 +134,10 @@ namespace dxvk {
|
||||||
|
|
||||||
void UpdateWindowCtx();
|
void UpdateWindowCtx();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static HRESULT GetFrontBufferDataGDI(IDirect3DSurface9* pDestSurface);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum BindingIds : uint32_t {
|
enum BindingIds : uint32_t {
|
||||||
|
|
Loading…
Reference in New Issue