Skip to content

Commit

Permalink
D3D11: Add support for HDR10 swapchains
Browse files Browse the repository at this point in the history
  • Loading branch information
flibitijibibo committed Jan 15, 2024
1 parent 508d572 commit c2bc660
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 4 deletions.
31 changes: 28 additions & 3 deletions src/FNA3D_Driver_D3D11.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ typedef struct D3D11SwapchainData
IDXGISwapChain *swapchain;
ID3D11RenderTargetView *swapchainRTView;
void *windowHandle;
FNA3D_SurfaceFormat format;
} D3D11SwapchainData;

#define WINDOW_SWAPCHAIN_DATA "FNA3D_D3D11Swapchain"
Expand Down Expand Up @@ -2533,6 +2534,7 @@ static void D3D11_INTERNAL_CreateSwapChain(
D3D11SwapchainData *swapchainData;
HWND dxgiHandle;
void* factory4;
IDXGISwapChain3 *swapchain3;
HRESULT res;

#ifdef FNA3D_DXVK_NATIVE
Expand Down Expand Up @@ -2636,10 +2638,26 @@ static void D3D11_INTERNAL_CreateSwapChain(
}
}

/* Set HDR10 colorspace, if applicable */
if (backBufferFormat == FNA3D_SURFACEFORMAT_RGBA1010102)
{
if (SUCCEEDED(IDXGISwapChain_QueryInterface(
swapchain,
&D3D_IID_IDXGISwapChain3,
(void**) &swapchain3
))) {
IDXGISwapChain3_SetColorSpace1(
swapchain3,
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020
);
}
}

swapchainData = (D3D11SwapchainData*) SDL_malloc(sizeof(D3D11SwapchainData));
swapchainData->swapchain = swapchain;
swapchainData->windowHandle = windowHandle;
swapchainData->swapchainRTView = NULL;
swapchainData->format = backBufferFormat;
SDL_SetWindowData((SDL_Window*) windowHandle, WINDOW_SWAPCHAIN_DATA, swapchainData);
if (renderer->swapchainDataCount >= renderer->swapchainDataCapacity)
{
Expand Down Expand Up @@ -3124,7 +3142,7 @@ static void D3D11_ReadBackbuffer(
ERROR_CHECK_RETURN("Could not get buffer from swapchain", )

backbufferTexture.handle = (ID3D11Resource*) swapchainBuffer;
backbufferTexture.format = FNA3D_SURFACEFORMAT_COLOR;
backbufferTexture.format = renderer->swapchainDatas[0]->format;
}

D3D11_GetTextureData2D(
Expand Down Expand Up @@ -3160,8 +3178,15 @@ static void D3D11_GetBackbufferSize(
static FNA3D_SurfaceFormat D3D11_GetBackbufferSurfaceFormat(
FNA3D_Renderer *driverData
) {
/* Copying OpenGL here. -caleb */
return FNA3D_SURFACEFORMAT_COLOR;
D3D11Renderer *renderer = (D3D11Renderer*) driverData;

if (renderer->backbuffer->type == BACKBUFFER_TYPE_D3D11)
{
return renderer->backbuffer->d3d11.surfaceFormat;
}

/* This path is only possible with a single window, 0 is safe */
return renderer->swapchainDatas[0]->format;
}

static FNA3D_DepthFormat D3D11_GetBackbufferDepthFormat(
Expand Down
260 changes: 259 additions & 1 deletion src/FNA3D_Driver_D3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static const IID D3D_IID_IDXGIFactory4 = {0x7632e1f5,0xee65,0x4dca,{0x87,0xfd,0x
static const IID D3D_IID_IDXGIFactory6 = {0xc1b6694f,0xff09,0x44a9,{0xb0,0x3c,0x77,0x90,0x0a,0x0a,0x1d,0x17}};
static const IID D3D_IID_IDXGIFactory5 = {0x7632e1f5,0xee65,0x4dca,{0x87,0xfd,0x84,0xcd,0x75,0xf8,0x83,0x8d}};
static const IID D3D_IID_IDXGIAdapter1 = {0x29038f61,0x3839,0x4626,{0x91,0xfd,0x08,0x68,0x79,0x01,0x1a,0x05}};
static const IID D3D_IID_IDXGISwapChain3 = {0x94d99bdb,0xf1f8,0x4ab0,{0xb2,0x36,0x7d,0xa0,0x17,0x0e,0xda,0xb1}};
static const IID D3D_IID_ID3D11Texture2D = {0x6f15aaf2,0xd208,0x4e89,{0x9a,0xb4,0x48,0x95,0x35,0xd3,0x4f,0x9c}};
static const IID D3D_IID_ID3DUserDefinedAnnotation = {0xb2daad8b,0x03d4,0x4dbf,{0x95,0xeb,0x32,0xab,0x4b,0x63,0xd0,0xab}};

Expand Down Expand Up @@ -130,9 +131,61 @@ struct ID3DUserDefinedAnnotation
#define ID3DUserDefinedAnnotation_GetStatus(This) \
( (This)->lpVtbl -> GetStatus(This) )

/* IDXGIFactory4 */
/* From dxgi1_2.h */

typedef enum DXGI_ALPHA_MODE {
DXGI_ALPHA_MODE_UNSPECIFIED = 0,
DXGI_ALPHA_MODE_PREMULTIPLIED = 1,
DXGI_ALPHA_MODE_STRAIGHT = 2,
DXGI_ALPHA_MODE_IGNORE = 3,
DXGI_ALPHA_MODE_FORCE_DWORD = 0x7fffffff
} DXGI_ALPHA_MODE;
typedef enum DXGI_SCALING {
DXGI_SCALING_STRETCH = 0,
DXGI_SCALING_NONE = 1,
DXGI_SCALING_ASPECT_RATIO_STRETCH = 2
} DXGI_SCALING;
typedef struct DXGI_SWAP_CHAIN_DESC1 {
UINT Width;
UINT Height;
DXGI_FORMAT Format;
WINBOOL Stereo;
DXGI_SAMPLE_DESC SampleDesc;
DXGI_USAGE BufferUsage;
UINT BufferCount;
DXGI_SCALING Scaling;
DXGI_SWAP_EFFECT SwapEffect;
DXGI_ALPHA_MODE AlphaMode;
UINT Flags;
} DXGI_SWAP_CHAIN_DESC1;
typedef struct DXGI_SWAP_CHAIN_FULLSCREEN_DESC {
DXGI_RATIONAL RefreshRate;
DXGI_MODE_SCANLINE_ORDER ScanlineOrdering;
DXGI_MODE_SCALING Scaling;
WINBOOL Windowed;
} DXGI_SWAP_CHAIN_FULLSCREEN_DESC;
typedef struct DXGI_PRESENT_PARAMETERS {
UINT DirtyRectsCount;
RECT *pDirtyRects;
RECT *pScrollRect;
POINT *pScrollOffset;
} DXGI_PRESENT_PARAMETERS;

/* From dxgi1_3.h */

typedef struct DXGI_MATRIX_3X2_F {
float _11;
float _12;
float _21;
float _22;
float _31;
float _32;
} DXGI_MATRIX_3X2_F;

/* From dxgi1_4.h, cleaned up a bit... */

/* IDXGIFactory4 */

typedef struct IDXGIFactory4 IDXGIFactory4;
typedef struct IDXGIFactory4Vtbl
{
Expand Down Expand Up @@ -287,6 +340,211 @@ struct IDXGIFactory4
#define IDXGIFactory4_Release(This) \
( (This)->lpVtbl -> Release(This) )

/* IDXGISwapChain3 */

typedef struct IDXGISwapChain3 IDXGISwapChain3;
typedef struct IDXGISwapChain3Vtbl
{
/*** IUnknown methods ***/
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IDXGISwapChain3 *This,
REFIID riid,
void **ppvObject);

ULONG ( STDMETHODCALLTYPE *AddRef )(
IDXGISwapChain3 *This);

ULONG ( STDMETHODCALLTYPE *Release )(
IDXGISwapChain3 *This);

/*** IDXGIObject methods ***/
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )(
IDXGISwapChain3 *This,
REFGUID guid,
UINT data_size,
const void *data);

HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )(
IDXGISwapChain3 *This,
REFGUID guid,
const IUnknown *object);

HRESULT ( STDMETHODCALLTYPE *GetPrivateData )(
IDXGISwapChain3 *This,
REFGUID guid,
UINT *data_size,
void *data);

HRESULT ( STDMETHODCALLTYPE *GetParent )(
IDXGISwapChain3 *This,
REFIID riid,
void **parent);

/*** IDXGIDeviceSubObject methods ***/
HRESULT ( STDMETHODCALLTYPE *GetDevice )(
IDXGISwapChain3 *This,
REFIID riid,
void **device);

/*** IDXGISwapChain methods ***/
HRESULT ( STDMETHODCALLTYPE *Present )(
IDXGISwapChain3 *This,
UINT sync_interval,
UINT flags);

HRESULT ( STDMETHODCALLTYPE *GetBuffer )(
IDXGISwapChain3 *This,
UINT buffer_idx,
REFIID riid,
void **surface);

HRESULT ( STDMETHODCALLTYPE *SetFullscreenState )(
IDXGISwapChain3 *This,
WINBOOL fullscreen,
IDXGIOutput *target);

HRESULT ( STDMETHODCALLTYPE *GetFullscreenState )(
IDXGISwapChain3 *This,
WINBOOL *fullscreen,
IDXGIOutput **target);

HRESULT ( STDMETHODCALLTYPE *GetDesc )(
IDXGISwapChain3 *This,
DXGI_SWAP_CHAIN_DESC *desc);

HRESULT ( STDMETHODCALLTYPE *ResizeBuffers )(
IDXGISwapChain3 *This,
UINT buffer_count,
UINT width,
UINT height,
DXGI_FORMAT format,
UINT flags);

HRESULT ( STDMETHODCALLTYPE *ResizeTarget )(
IDXGISwapChain3 *This,
const DXGI_MODE_DESC *target_mode_desc);

HRESULT ( STDMETHODCALLTYPE *GetContainingOutput )(
IDXGISwapChain3 *This,
IDXGIOutput **output);

HRESULT ( STDMETHODCALLTYPE *GetFrameStatistics )(
IDXGISwapChain3 *This,
DXGI_FRAME_STATISTICS *stats);

HRESULT ( STDMETHODCALLTYPE *GetLastPresentCount )(
IDXGISwapChain3 *This,
UINT *last_present_count);

/*** IDXGISwapChain1 methods ***/
HRESULT ( STDMETHODCALLTYPE *GetDesc1 )(
IDXGISwapChain3 *This,
DXGI_SWAP_CHAIN_DESC1 *pDesc);

HRESULT ( STDMETHODCALLTYPE *GetFullscreenDesc )(
IDXGISwapChain3 *This,
DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pDesc);

HRESULT ( STDMETHODCALLTYPE *GetHwnd )(
IDXGISwapChain3 *This,
HWND *pHwnd);

HRESULT ( STDMETHODCALLTYPE *GetCoreWindow )(
IDXGISwapChain3 *This,
REFIID refiid,
void **ppUnk);

HRESULT ( STDMETHODCALLTYPE *Present1 )(
IDXGISwapChain3 *This,
UINT SyncInterval,
UINT PresentFlags,
const DXGI_PRESENT_PARAMETERS *pPresentParameters);

WINBOOL ( STDMETHODCALLTYPE *IsTemporaryMonoSupported )(
IDXGISwapChain3 *This);

HRESULT ( STDMETHODCALLTYPE *GetRestrictToOutput )(
IDXGISwapChain3 *This,
IDXGIOutput **ppRestrictToOutput);

HRESULT ( STDMETHODCALLTYPE *SetBackgroundColor )(
IDXGISwapChain3 *This,
const DXGI_RGBA *pColor);

HRESULT ( STDMETHODCALLTYPE *GetBackgroundColor )(
IDXGISwapChain3 *This,
DXGI_RGBA *pColor);

HRESULT ( STDMETHODCALLTYPE *SetRotation )(
IDXGISwapChain3 *This,
DXGI_MODE_ROTATION Rotation);

HRESULT ( STDMETHODCALLTYPE *GetRotation )(
IDXGISwapChain3 *This,
DXGI_MODE_ROTATION *pRotation);

/*** IDXGISwapChain2 methods ***/
HRESULT ( STDMETHODCALLTYPE *SetSourceSize )(
IDXGISwapChain3 *This,
UINT width,
UINT height);

HRESULT ( STDMETHODCALLTYPE *GetSourceSize )(
IDXGISwapChain3 *This,
UINT *width,
UINT *height);

HRESULT ( STDMETHODCALLTYPE *SetMaximumFrameLatency )(
IDXGISwapChain3 *This,
UINT max_latency);

HRESULT ( STDMETHODCALLTYPE *GetMaximumFrameLatency )(
IDXGISwapChain3 *This,
UINT *max_latency);

HANDLE ( STDMETHODCALLTYPE *GetFrameLatencyWaitableObject )(
IDXGISwapChain3 *This);

HRESULT ( STDMETHODCALLTYPE *SetMatrixTransform )(
IDXGISwapChain3 *This,
const DXGI_MATRIX_3X2_F *matrix);

HRESULT ( STDMETHODCALLTYPE *GetMatrixTransform )(
IDXGISwapChain3 *This,
DXGI_MATRIX_3X2_F *matrix);

/*** IDXGISwapChain3 methods ***/
UINT ( STDMETHODCALLTYPE *GetCurrentBackBufferIndex )(
IDXGISwapChain3 *This);

HRESULT ( STDMETHODCALLTYPE *CheckColorSpaceSupport )(
IDXGISwapChain3 *This,
DXGI_COLOR_SPACE_TYPE colour_space,
UINT *colour_space_support);

HRESULT ( STDMETHODCALLTYPE *SetColorSpace1 )(
IDXGISwapChain3 *This,
DXGI_COLOR_SPACE_TYPE colour_space);

HRESULT ( STDMETHODCALLTYPE *ResizeBuffers1 )(
IDXGISwapChain3 *This,
UINT buffer_count,
UINT width,
UINT height,
DXGI_FORMAT format,
UINT flags,
const UINT *node_mask,
IUnknown *const *present_queue);
} IDXGISwapChain3Vtbl;

struct IDXGISwapChain3
{
struct IDXGISwapChain3Vtbl *lpVtbl;
};

#define IDXGISwapChain3_SetColorSpace1(This, colour_space) \
( (This)->lpVtbl -> SetColorSpace1(This, colour_space) )

/* IDXGIFactory5 */
/* From dxgi1_5.h, cleaned up a bit... */

Expand Down

0 comments on commit c2bc660

Please sign in to comment.