mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 04:29:15 +01:00
[dxgi] Implemented SDL-backed DxgiSwapChain methods
This commit is contained in:
parent
f3a37068bb
commit
26e662e12c
@ -12,15 +12,40 @@ namespace dxvk {
|
||||
: m_factory (factory),
|
||||
m_desc (*pDesc) {
|
||||
|
||||
// Retrieve a device pointer that allows us to
|
||||
// communicate with the underlying D3D device
|
||||
if (FAILED(pDevice->QueryInterface(__uuidof(IDXVKDevice),
|
||||
reinterpret_cast<void**>(&m_device))))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Invalid device");
|
||||
|
||||
// Initialize frame statistics
|
||||
m_stats.PresentCount = 0;
|
||||
m_stats.PresentRefreshCount = 0;
|
||||
m_stats.SyncRefreshCount = 0;
|
||||
m_stats.SyncQPCTime.QuadPart = 0;
|
||||
m_stats.SyncGPUTime.QuadPart = 0;
|
||||
|
||||
// Create SDL window handle
|
||||
m_window = SDL_CreateWindowFrom(m_desc.OutputWindow);
|
||||
|
||||
if (m_window == nullptr) {
|
||||
throw DxvkError(str::format(
|
||||
"DxgiSwapChain::DxgiSwapChain: Failed to create window:\n",
|
||||
SDL_GetError()));
|
||||
}
|
||||
|
||||
// Set initial window mode and fullscreen state
|
||||
if (FAILED(this->ResizeTarget(&pDesc->BufferDesc)))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial display mode");
|
||||
|
||||
if (FAILED(this->SetFullscreenState(!pDesc->Windowed, nullptr)))
|
||||
throw DxvkError("DxgiSwapChain::DxgiSwapChain: Failed to set initial fullscreen state");
|
||||
}
|
||||
|
||||
|
||||
DxgiSwapChain::~DxgiSwapChain() {
|
||||
|
||||
// We do not release the SDL window handle here since
|
||||
// that would destroy the underlying window as well.
|
||||
}
|
||||
|
||||
|
||||
@ -46,44 +71,87 @@ namespace dxvk {
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
Logger::err("DxgiSwapChain::GetBuffer: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetContainingOutput(IDXGIOutput** ppOutput) {
|
||||
Logger::err("DxgiSwapChain::GetContainingOutput: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
if (ppOutput != nullptr)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
// We can use the display index returned by SDL to query the
|
||||
// containing output, since DxgiAdapter::EnumOutputs uses the
|
||||
// same output IDs.
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
int32_t displayId = SDL_GetWindowDisplayIndex(m_window);
|
||||
|
||||
if (displayId < 0) {
|
||||
Logger::err("DxgiSwapChain::GetContainingOutput: Failed to query window display index");
|
||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
Com<IDXGIAdapter> adapter;
|
||||
|
||||
if (FAILED(m_device->GetAdapter(&adapter)))
|
||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
||||
|
||||
return adapter->EnumOutputs(displayId, ppOutput);
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) {
|
||||
Logger::err("DxgiSwapChain::GetDesc: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
if (pDesc == nullptr)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
*pDesc = m_desc;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) {
|
||||
Logger::err("DxgiSwapChain::GetFrameStatistics: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
if (pStats == nullptr)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
*pStats = m_stats;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetFullscreenState(
|
||||
BOOL* pFullscreen,
|
||||
IDXGIOutput** ppTarget) {
|
||||
Logger::err("DxgiSwapChain::GetFullscreenState: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (pFullscreen != nullptr)
|
||||
*pFullscreen = !m_desc.Windowed;
|
||||
|
||||
if ((ppTarget != nullptr) && !m_desc.Windowed)
|
||||
hr = this->GetContainingOutput(ppTarget);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::GetLastPresentCount(UINT* pLastPresentCount) {
|
||||
Logger::err("DxgiSwapChain::GetLastPresentCount: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
if (pLastPresentCount == nullptr)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
*pLastPresentCount = m_stats.PresentCount;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::Present(UINT SyncInterval, UINT Flags) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
Logger::err("DxgiSwapChain::Present: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
@ -95,22 +163,90 @@ namespace dxvk {
|
||||
UINT Height,
|
||||
DXGI_FORMAT NewFormat,
|
||||
UINT SwapChainFlags) {
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
Logger::err("DxgiSwapChain::ResizeBuffers: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) {
|
||||
Logger::err("DxgiSwapChain::ResizeTarget: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
if (pNewTargetParameters == nullptr)
|
||||
return DXGI_ERROR_INVALID_CALL;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_desc.BufferDesc = *pNewTargetParameters;
|
||||
|
||||
// Applies to windowed mode
|
||||
SDL_SetWindowSize(m_window,
|
||||
pNewTargetParameters->Width,
|
||||
pNewTargetParameters->Height);
|
||||
|
||||
// Applies to fullscreen mode
|
||||
SDL_DisplayMode displayMode;
|
||||
displayMode.format = SDL_PIXELFORMAT_RGBA32;
|
||||
displayMode.w = pNewTargetParameters->Width;
|
||||
displayMode.h = pNewTargetParameters->Height;
|
||||
displayMode.refresh_rate = pNewTargetParameters->RefreshRate.Numerator
|
||||
/ pNewTargetParameters->RefreshRate.Denominator;
|
||||
displayMode.driverdata = nullptr;
|
||||
|
||||
if (SDL_SetWindowDisplayMode(m_window, &displayMode)) {
|
||||
throw DxvkError(str::format(
|
||||
"DxgiSwapChain::ResizeTarget: Failed to set display mode:\n",
|
||||
SDL_GetError()));
|
||||
return DXGI_ERROR_DRIVER_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT DxgiSwapChain::SetFullscreenState(
|
||||
BOOL Fullscreen,
|
||||
IDXGIOutput* pTarget) {
|
||||
Logger::err("DxgiSwapChain::SetFullscreenState: Not implemented");
|
||||
return E_NOTIMPL;
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// Unconditionally reset the swap chain to windowed mode first.
|
||||
// This required if the application wants to move the window to
|
||||
// a different display while remaining in fullscreen mode.
|
||||
if (SDL_SetWindowFullscreen(m_window, 0)) {
|
||||
Logger::err(str::format(
|
||||
"DxgiSwapChain::SetFullscreenState: Failed to set windowed mode:\n",
|
||||
SDL_GetError()));
|
||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
|
||||
m_desc.Windowed = !Fullscreen;
|
||||
|
||||
if (Fullscreen) {
|
||||
// If a target output is specified, we need to move the
|
||||
// window to that output first while in windowed mode.
|
||||
if (pTarget != nullptr) {
|
||||
DXGI_OUTPUT_DESC outputDesc;
|
||||
|
||||
if (FAILED(pTarget->GetDesc(&outputDesc))) {
|
||||
Logger::err("DxgiSwapChain::SetFullscreenState: Failed to query output properties");
|
||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
|
||||
SDL_SetWindowPosition(m_window,
|
||||
outputDesc.DesktopCoordinates.left,
|
||||
outputDesc.DesktopCoordinates.top);
|
||||
}
|
||||
|
||||
// Now that the window is located at the target location,
|
||||
// SDL should fullscreen it on the requested display. We
|
||||
// only use borderless fullscreen for now, may be changed.
|
||||
if (SDL_SetWindowFullscreen(m_window, SDL_WINDOW_FULLSCREEN_DESKTOP)) {
|
||||
Logger::err(str::format(
|
||||
"DxgiSwapChain::SetFullscreenState: Failed to set fullscreen mode:\n",
|
||||
SDL_GetError()));
|
||||
return DXGI_ERROR_NOT_CURRENTLY_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -73,10 +73,15 @@ namespace dxvk {
|
||||
|
||||
private:
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
Com<DxgiFactory> m_factory;
|
||||
Com<IDXVKDevice> m_device;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||
DXGI_SWAP_CHAIN_DESC m_desc;
|
||||
DXGI_FRAME_STATISTICS m_stats;
|
||||
|
||||
SDL_Window* m_window = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
|
||||
HINSTANCE hPrevInstance,
|
||||
LPSTR lpCmdLine,
|
||||
int nCmdShow) {
|
||||
Com<IDXGIFactory> factory = nullptr;
|
||||
Com<IDXGIFactory> factory;
|
||||
|
||||
if (CreateDXGIFactory(__uuidof(IDXGIFactory),
|
||||
reinterpret_cast<void**>(&factory)) != S_OK) {
|
||||
@ -19,7 +19,7 @@ int WINAPI WinMain(HINSTANCE hInstance,
|
||||
return 1;
|
||||
}
|
||||
|
||||
Com<IDXGIAdapter> adapter = nullptr;
|
||||
Com<IDXGIAdapter> adapter;
|
||||
|
||||
for (UINT i = 0; factory->EnumAdapters(i, &adapter) == S_OK; i++) {
|
||||
DXGI_ADAPTER_DESC adapterDesc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user