forked from MoonsideGames/Refresh
Implement ClaimWindow, mostly copied from Vulkan and FNA3D D3D11
parent
8b999aca93
commit
0e5da8a2ea
|
@ -46,7 +46,7 @@
|
||||||
#define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice"
|
#define D3D11_CREATE_DEVICE_FUNC "D3D11CreateDevice"
|
||||||
#define D3DCOMPILE_FUNC "D3DCompile"
|
#define D3DCOMPILE_FUNC "D3DCompile"
|
||||||
#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
|
#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
|
||||||
#define WINDOW_SWAPCHAIN_DATA "Refresh_D3D11Swapchain"
|
#define WINDOW_DATA "Refresh_D3D11WindowData"
|
||||||
|
|
||||||
#define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!");
|
#define NOT_IMPLEMENTED SDL_assert(0 && "Not implemented!");
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ typedef HRESULT(WINAPI *PFN_D3DCOMPILE)(
|
||||||
|
|
||||||
/* Conversions */
|
/* Conversions */
|
||||||
|
|
||||||
static DXGI_FORMAT RefreshToD3D11_SurfaceFormat[] =
|
static DXGI_FORMAT RefreshToD3D11_TextureFormat[] =
|
||||||
{
|
{
|
||||||
DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */
|
DXGI_FORMAT_R8G8B8A8_UNORM, /* R8G8B8A8 */
|
||||||
DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */
|
DXGI_FORMAT_B8G8R8A8_UNORM, /* B8G8R8A8 */
|
||||||
|
@ -233,6 +233,19 @@ static D3D11_TEXTURE_ADDRESS_MODE RefreshToD3D11_SamplerAddressMode[] =
|
||||||
|
|
||||||
/* Structs */
|
/* Structs */
|
||||||
|
|
||||||
|
typedef struct SwapchainData
|
||||||
|
{
|
||||||
|
IDXGISwapChain *swapchain;
|
||||||
|
ID3D11RenderTargetView *swapchainRTView;
|
||||||
|
} SwapchainData;
|
||||||
|
|
||||||
|
typedef struct WindowData
|
||||||
|
{
|
||||||
|
void* windowHandle;
|
||||||
|
uint8_t allowTearing;
|
||||||
|
SwapchainData *swapchainData;
|
||||||
|
} WindowData;
|
||||||
|
|
||||||
typedef struct D3D11Renderer
|
typedef struct D3D11Renderer
|
||||||
{
|
{
|
||||||
ID3D11Device *device;
|
ID3D11Device *device;
|
||||||
|
@ -244,8 +257,12 @@ typedef struct D3D11Renderer
|
||||||
void *d3dcompiler_dll;
|
void *d3dcompiler_dll;
|
||||||
|
|
||||||
uint8_t debugMode;
|
uint8_t debugMode;
|
||||||
D3D_FEATURE_LEVEL featureLevel;
|
D3D_FEATURE_LEVEL featureLevel; /* FIXME: Do we need this? */
|
||||||
PFN_D3DCOMPILE D3DCompileFunc;
|
PFN_D3DCOMPILE D3DCompileFunc;
|
||||||
|
|
||||||
|
WindowData **claimedWindows;
|
||||||
|
uint32_t claimedWindowCount;
|
||||||
|
uint32_t claimedWindowCapacity;
|
||||||
} D3D11Renderer;
|
} D3D11Renderer;
|
||||||
|
|
||||||
/* Logging */
|
/* Logging */
|
||||||
|
@ -693,14 +710,196 @@ static void D3D11_BindComputeTextures(
|
||||||
|
|
||||||
/* Window and Swapchain Management */
|
/* Window and Swapchain Management */
|
||||||
|
|
||||||
|
static WindowData* D3D11_INTERNAL_FetchWindowData(
|
||||||
|
void *windowHandle
|
||||||
|
) {
|
||||||
|
return (WindowData*) SDL_GetWindowData(windowHandle, WINDOW_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void D3D11_INTERNAL_ResolveSwapChainModeDescription(
|
||||||
|
IUnknown *device,
|
||||||
|
IDXGIAdapter *adapter,
|
||||||
|
IDXGIFactory1 *factory,
|
||||||
|
HWND window,
|
||||||
|
DXGI_MODE_DESC *modeDescription,
|
||||||
|
DXGI_MODE_DESC *swapChainDescription
|
||||||
|
) {
|
||||||
|
HMONITOR monitor;
|
||||||
|
int iAdapter = 0, iOutput;
|
||||||
|
IDXGIAdapter1* pAdapter;
|
||||||
|
IDXGIOutput *output;
|
||||||
|
DXGI_OUTPUT_DESC description;
|
||||||
|
|
||||||
|
/* Find the output (on any adapter) attached to the monitor that holds our window */
|
||||||
|
monitor = MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
while (SUCCEEDED(IDXGIFactory1_EnumAdapters1(factory, iAdapter++, &pAdapter)))
|
||||||
|
{
|
||||||
|
iOutput = 0;
|
||||||
|
while (SUCCEEDED(IDXGIAdapter_EnumOutputs(pAdapter, iOutput++, &output)))
|
||||||
|
{
|
||||||
|
IDXGIOutput_GetDesc(output, &description);
|
||||||
|
if (description.Monitor == monitor)
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(IDXGIOutput_FindClosestMatchingMode(output, modeDescription, swapChainDescription, device)))
|
||||||
|
{
|
||||||
|
IDXGIOutput_Release(output);
|
||||||
|
IDXGIAdapter1_Release(pAdapter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDXGIOutput_Release(output);
|
||||||
|
}
|
||||||
|
IDXGIAdapter1_Release(pAdapter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t D3D11_INTERNAL_CreateSwapchain(
|
||||||
|
D3D11Renderer *renderer,
|
||||||
|
WindowData *windowData
|
||||||
|
) {
|
||||||
|
SDL_SysWMinfo info;
|
||||||
|
HWND dxgiHandle;
|
||||||
|
DXGI_MODE_DESC swapchainBufferDesc;
|
||||||
|
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
||||||
|
IDXGIFactory1 *pParent;
|
||||||
|
IDXGISwapChain *swapchain;
|
||||||
|
SwapchainData *swapchainData;
|
||||||
|
HRESULT res;
|
||||||
|
|
||||||
|
/* Get the DXGI handle */
|
||||||
|
SDL_VERSION(&info.version);
|
||||||
|
SDL_GetWindowWMInfo((SDL_Window*) windowData->windowHandle, &info);
|
||||||
|
dxgiHandle = info.info.win.window;
|
||||||
|
|
||||||
|
/* Initialize the swapchain buffer descriptor */
|
||||||
|
swapchainBufferDesc.Width = 0;
|
||||||
|
swapchainBufferDesc.Height = 0;
|
||||||
|
swapchainBufferDesc.RefreshRate.Numerator = 0;
|
||||||
|
swapchainBufferDesc.RefreshRate.Denominator = 0;
|
||||||
|
swapchainBufferDesc.Format = RefreshToD3D11_TextureFormat[REFRESH_TEXTUREFORMAT_R8G8B8A8];
|
||||||
|
swapchainBufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||||
|
swapchainBufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||||
|
|
||||||
|
/* Get the closest matching mode we can from the current monitor */
|
||||||
|
D3D11_INTERNAL_ResolveSwapChainModeDescription(
|
||||||
|
(IUnknown*) renderer->device,
|
||||||
|
(IDXGIAdapter*) renderer->adapter,
|
||||||
|
(IDXGIFactory1*) renderer->factory,
|
||||||
|
dxgiHandle,
|
||||||
|
&swapchainBufferDesc,
|
||||||
|
&swapchainDesc.BufferDesc
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Initialize the swapchain descriptor */
|
||||||
|
swapchainDesc.BufferDesc = swapchainBufferDesc; /* FIXME: I think this is wrong, and it's wrong in FNA3D too! */
|
||||||
|
swapchainDesc.SampleDesc.Count = 1;
|
||||||
|
swapchainDesc.SampleDesc.Quality = 0;
|
||||||
|
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
swapchainDesc.BufferCount = 3;
|
||||||
|
swapchainDesc.OutputWindow = dxgiHandle;
|
||||||
|
swapchainDesc.Windowed = 1;
|
||||||
|
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
swapchainDesc.Flags = 0;
|
||||||
|
|
||||||
|
/* Create the swapchain! */
|
||||||
|
res = IDXGIFactory1_CreateSwapChain(
|
||||||
|
(IDXGIFactory1*) renderer->factory,
|
||||||
|
(IUnknown*) renderer->device,
|
||||||
|
&swapchainDesc,
|
||||||
|
&swapchain
|
||||||
|
);
|
||||||
|
ERROR_CHECK("Could not create swapchain");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The swapchain's parent is a separate factory from the factory that
|
||||||
|
* we used to create the swapchain, and only that parent can be used to
|
||||||
|
* set the window association. Trying to set an association on our factory
|
||||||
|
* will silently fail and doesn't even verify arguments or return errors.
|
||||||
|
* See https://gamedev.net/forums/topic/634235-dxgidisabling-altenter/4999955/
|
||||||
|
*/
|
||||||
|
res = IDXGISwapChain_GetParent(
|
||||||
|
swapchain,
|
||||||
|
&D3D_IID_IDXGIFactory1,
|
||||||
|
(void**) &pParent
|
||||||
|
);
|
||||||
|
if (FAILED(res))
|
||||||
|
{
|
||||||
|
Refresh_LogWarn(
|
||||||
|
"Could not get swapchain parent! Error Code: %08X",
|
||||||
|
res
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Disable DXGI window crap */
|
||||||
|
res = IDXGIFactory1_MakeWindowAssociation(
|
||||||
|
pParent,
|
||||||
|
dxgiHandle,
|
||||||
|
DXGI_MWA_NO_WINDOW_CHANGES
|
||||||
|
);
|
||||||
|
if (FAILED(res))
|
||||||
|
{
|
||||||
|
Refresh_LogWarn(
|
||||||
|
"MakeWindowAssociation failed! Error Code: %08X",
|
||||||
|
res
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the swapchain data */
|
||||||
|
swapchainData = (SwapchainData*) SDL_malloc(sizeof(SwapchainData));
|
||||||
|
swapchainData->swapchain = swapchain;
|
||||||
|
swapchainData->swapchainRTView = NULL;
|
||||||
|
|
||||||
|
windowData->swapchainData = swapchainData;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t D3D11_ClaimWindow(
|
static uint8_t D3D11_ClaimWindow(
|
||||||
Refresh_Renderer *driverData,
|
Refresh_Renderer *driverData,
|
||||||
void *windowHandle,
|
void *windowHandle,
|
||||||
Refresh_PresentMode presentMode
|
Refresh_PresentMode presentMode
|
||||||
) {
|
) {
|
||||||
NOT_IMPLEMENTED
|
D3D11Renderer *renderer = (D3D11Renderer*) driverData;
|
||||||
|
WindowData *windowData = D3D11_INTERNAL_FetchWindowData(windowHandle);
|
||||||
|
|
||||||
|
if (windowData == NULL)
|
||||||
|
{
|
||||||
|
windowData = (WindowData*) SDL_malloc(sizeof(WindowData));
|
||||||
|
windowData->windowHandle = windowHandle;
|
||||||
|
windowData->allowTearing = presentMode == REFRESH_PRESENTMODE_IMMEDIATE;
|
||||||
|
|
||||||
|
if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData))
|
||||||
|
{
|
||||||
|
SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_DATA, windowData);
|
||||||
|
|
||||||
|
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity)
|
||||||
|
{
|
||||||
|
renderer->claimedWindowCapacity *= 2;
|
||||||
|
renderer->claimedWindows = SDL_realloc(
|
||||||
|
renderer->claimedWindows,
|
||||||
|
renderer->claimedWindowCapacity * sizeof(WindowData*)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
||||||
|
renderer->claimedWindowCount += 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Refresh_LogError("Could not create swapchain, failed to claim window!");
|
||||||
|
SDL_free(windowData);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Refresh_LogWarn("Window already claimed!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t D3D11_UnclaimWindow(
|
static uint8_t D3D11_UnclaimWindow(
|
||||||
Refresh_Renderer *driverData,
|
Refresh_Renderer *driverData,
|
||||||
|
@ -725,7 +924,6 @@ static Refresh_TextureFormat D3D11_GetSwapchainFormat(
|
||||||
Refresh_Renderer *driverData,
|
Refresh_Renderer *driverData,
|
||||||
void *windowHandle
|
void *windowHandle
|
||||||
) {
|
) {
|
||||||
NOT_IMPLEMENTED
|
|
||||||
return REFRESH_TEXTUREFORMAT_R8G8B8A8;
|
return REFRESH_TEXTUREFORMAT_R8G8B8A8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue