2016-07-12 00:40:13 +00:00
# include "quakedef.h"
# ifdef D3D11QUAKE
# include "winquake.h"
# include "gl_draw.h"
# include "glquake.h"
# include "shader.h"
# include "renderque.h"
# define COBJMACROS
# include <d3d11.h>
ID3D11Device * pD3DDev11 ;
ID3D11DeviceContext * d3ddevctx ;
//#include <d3d11_1.h>
//ID3D11DeviceContext1 *d3ddevctx1;
# ifdef WINRT //winrt crap has its own non-hwnd window crap, after years of microsoft forcing everyone to use hwnds for everything. I wonder why they don't have that many winrt apps.
# pragma comment(lib, "dxgi.lib")
# pragma comment(lib, "D3D11.lib")
# include "dxgi1_2.h"
# else
/*Fixup outdated windows headers*/
# ifndef WM_XBUTTONDOWN
# define WM_XBUTTONDOWN 0x020B
# define WM_XBUTTONUP 0x020C
# endif
# ifndef MK_XBUTTON1
# define MK_XBUTTON1 0x0020
# endif
# ifndef MK_XBUTTON2
# define MK_XBUTTON2 0x0040
# endif
// copied from DarkPlaces in an attempt to grab more buttons
# ifndef MK_XBUTTON3
# define MK_XBUTTON3 0x0080
# endif
# ifndef MK_XBUTTON4
# define MK_XBUTTON4 0x0100
# endif
# ifndef MK_XBUTTON5
# define MK_XBUTTON5 0x0200
# endif
# ifndef MK_XBUTTON6
# define MK_XBUTTON6 0x0400
# endif
# ifndef MK_XBUTTON7
# define MK_XBUTTON7 0x0800
# endif
# ifndef WM_INPUT
# define WM_INPUT 255
# endif
# endif
# define DEFINE_QGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
2017-02-21 20:22:07 +00:00
const GUID DECLSPEC_SELECTANY name \
= { l , w1 , w2 , { b1 , b2 , b3 , b4 , b5 , b6 , b7 , b8 } }
2016-07-12 00:40:13 +00:00
DEFINE_QGUID ( qIID_ID3D11Texture2D , 0x6f15aaf2 , 0xd208 , 0x4e89 , 0x9a , 0xb4 , 0x48 , 0x95 , 0x35 , 0xd3 , 0x4f , 0x9c ) ;
# ifdef WINRT
IDXGISwapChain1 * d3dswapchain ;
# else
IDXGISwapChain * d3dswapchain ;
# endif
IDXGIOutput * d3dscreen ;
ID3D11RenderTargetView * fb_backbuffer ;
ID3D11DepthStencilView * fb_backdepthstencil ;
void * d3d11mod ;
static unsigned int d3d11multisample_count , d3d11multisample_quality ;
qboolean vid_initializing ;
extern qboolean scr_initialized ; // ready to draw
extern qboolean scr_drawloading ;
extern qboolean scr_con_forcedraw ;
static qboolean d3d_resized ;
//sound/error code needs this
HWND mainwindow ;
//input code needs these
int window_center_x , window_center_y ;
RECT window_rect ;
int window_x , window_y ;
static void released3dbackbuffer ( void ) ;
static qboolean resetd3dbackbuffer ( int width , int height ) ;
#if 0 //def _DEBUG
# include <dxgidebug.h>
const GUID IID_IDXGIDebug = { 0x119E7452 , 0xDE9E , 0x40fe , { 0x88 , 0x06 , 0x88 , 0xF9 , 0x0C , 0x12 , 0xB4 , 0x41 } } ;
const GUID DXGI_DEBUG_ALL = { 0xe48ae283 , 0xda80 , 0x490b , { 0x87 , 0xe6 , 0x43 , 0xe9 , 0xa9 , 0xcf , 0xda , 0x8 } } ;
void DoDXGIDebug ( void )
{
IDXGIDebug * dbg = NULL ;
HRESULT ( WINAPI * pDXGIGetDebugInterface ) ( REFIID riid , void * * ppDebug ) ;
dllfunction_t dxdidebugfuncs [ ] =
{
{ ( void * * ) & pDXGIGetDebugInterface , " DXGIGetDebugInterface " } ,
{ NULL }
} ;
pDXGIGetDebugInterface = NULL ;
Sys_LoadLibrary ( " dxgidebug " , dxdidebugfuncs ) ;
pDXGIGetDebugInterface ( & IID_IDXGIDebug , & dbg ) ;
if ( dbg )
{
IDXGIDebug_ReportLiveObjects ( dbg , DXGI_DEBUG_ALL , DXGI_DEBUG_RLO_ALL ) ;
IDXGIDebug_Release ( dbg ) ;
}
}
# else
# define DoDXGIDebug()
# endif
char * D3D_NameForResult ( HRESULT hr )
{
if ( hr = = DXGI_ERROR_DEVICE_REMOVED & & pD3DDev11 )
hr = ID3D11Device_GetDeviceRemovedReason ( pD3DDev11 ) ;
switch ( hr )
{
case E_OUTOFMEMORY : return " E_OUTOFMEMORY " ;
case E_NOINTERFACE : return " E_NOINTERFACE " ;
case DXGI_ERROR_DEVICE_HUNG : return " DXGI_ERROR_DEVICE_HUNG " ;
case DXGI_ERROR_DEVICE_REMOVED : return " DXGI_ERROR_DEVICE_REMOVED " ;
case DXGI_ERROR_DEVICE_RESET : return " DXGI_ERROR_DEVICE_RESET " ;
case DXGI_ERROR_DRIVER_INTERNAL_ERROR : return " DXGI_ERROR_DRIVER_INTERNAL_ERROR " ;
case DXGI_ERROR_INVALID_CALL : return " DXGI_ERROR_INVALID_CALL " ;
default : return va ( " %lx " , hr ) ;
}
}
static void D3D11_PresentOrCrash ( void )
{
extern cvar_t vid_vsync ;
RSpeedMark ( ) ;
HRESULT hr = IDXGISwapChain_Present ( d3dswapchain , vid_vsync . ival , 0 ) ;
if ( FAILED ( hr ) )
Sys_Error ( " IDXGISwapChain_Present: %s \n " , D3D_NameForResult ( hr ) ) ;
RSpeedEnd ( RSPEED_PRESENT ) ;
}
typedef enum { MS_WINDOWED , MS_FULLSCREEN , MS_FULLDIB , MS_UNINIT } modestate_t ;
static modestate_t modestate ;
//FIXME: need to push/pop render targets like gl does, to not harm shadowmaps/refraction/etc.
void D3D11_ApplyRenderTargets ( qboolean usedepth )
{
unsigned int width = 0 , height = 0 ;
int i ;
texid_t textures [ 1 ] ;
texid_t depth ;
ID3D11RenderTargetView * rtv [ sizeof ( textures ) / sizeof ( textures [ 0 ] ) ] ;
ID3D11DepthStencilView * dsv ;
for ( i = 0 ; i < sizeof ( textures ) / sizeof ( textures [ 0 ] ) ; i + + )
{
if ( ! * r_refdef . rt_destcolour [ i ] . texname )
break ;
textures [ i ] = R2D_RT_GetTexture ( r_refdef . rt_destcolour [ i ] . texname , & width , & height ) ;
if ( textures [ i ] - > ptr2 )
{
ID3D11ShaderResourceView_Release ( ( ID3D11ShaderResourceView * ) textures [ i ] - > ptr2 ) ;
textures [ i ] - > ptr2 = NULL ;
}
ID3D11Device_CreateRenderTargetView ( pD3DDev11 , textures [ i ] - > ptr , NULL , & rtv [ i ] ) ;
}
if ( usedepth )
{
if ( * r_refdef . rt_depth . texname )
depth = R2D_RT_GetTexture ( r_refdef . rt_depth . texname , & width , & height ) ;
else
2016-10-22 07:06:51 +00:00
depth = R2D_RT_Configure ( " depth " , width , height , TF_DEPTH24 , RT_IMAGEFLAGS ) ;
2016-07-12 00:40:13 +00:00
}
else
depth = NULL ;
if ( depth & & depth - > ptr )
{
if ( depth - > ptr2 )
{
ID3D11DepthStencilView_Release ( ( ID3D11DepthStencilView * ) depth - > ptr2 ) ;
depth - > ptr2 = NULL ;
}
ID3D11Device_CreateDepthStencilView ( pD3DDev11 , depth - > ptr , NULL , & dsv ) ;
}
else
dsv = NULL ;
ID3D11DeviceContext_OMSetRenderTargets ( d3ddevctx , i , rtv , dsv ) ;
for ( i = 0 ; i < sizeof ( textures ) / sizeof ( textures [ 0 ] ) ; i + + )
if ( rtv [ i ] )
ID3D11RenderTargetView_Release ( rtv [ i ] ) ;
if ( dsv )
{
ID3D11DeviceContext_ClearDepthStencilView ( d3ddevctx , dsv , D3D11_CLEAR_DEPTH , 1 , 0 ) ; //is it faster to clear the stencil too?
ID3D11DepthStencilView_Release ( dsv ) ;
}
}
# ifndef WINRT //winrt crap has its own non-hwnd window crap, after years of microsoft forcing everyone to use hwnds for everything. I wonder why they don't have that many winrt apps.
static void D3DVID_UpdateWindowStatus ( HWND hWnd )
{
POINT p ;
RECT nr ;
int window_width , window_height ;
GetClientRect ( hWnd , & nr ) ;
// Sys_Printf("Update: %i %i %i %i\n", nr.left, nr.top, nr.right, nr.bottom);
//if its bad then we're probably minimised
if ( nr . right < = nr . left )
return ;
if ( nr . bottom < = nr . top )
return ;
p . x = 0 ;
p . y = 0 ;
ClientToScreen ( hWnd , & p ) ;
window_x = p . x ;
window_y = p . y ;
window_width = nr . right - nr . left ;
window_height = nr . bottom - nr . top ;
// vid.pixelwidth = window_width;
// vid.pixelheight = window_height;
window_rect . left = window_x ;
window_rect . top = window_y ;
window_rect . right = window_x + window_width ;
window_rect . bottom = window_y + window_height ;
window_center_x = ( window_rect . left + window_rect . right ) / 2 ;
window_center_y = ( window_rect . top + window_rect . bottom ) / 2 ;
// Sys_Printf("Window: %i %i %i %i\n", window_x, window_y, window_width, window_height);
INS_UpdateClipCursor ( ) ;
}
static qboolean D3D11AppActivate ( BOOL fActive , BOOL minimize )
/****************************************************************************
*
* Function : AppActivate
* Parameters : fActive - True if app is activating
*
* Description : If the application is activating , then swap the system
* into SYSPAL_NOSTATIC mode so that our palettes will display
* correctly .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
{
static BOOL sound_active ;
if ( vid . activeapp = = fActive & & Minimized = = minimize )
return false ; //so windows doesn't crash us over and over again.
vid . activeapp = fActive ;
Minimized = minimize ;
// enable/disable sound on focus gain/loss
if ( ! vid . activeapp & & sound_active )
{
S_BlockSound ( ) ;
sound_active = false ;
}
else if ( vid . activeapp & & ! sound_active )
{
S_UnblockSound ( ) ;
sound_active = true ;
}
INS_UpdateGrabs ( modestate ! = MS_WINDOWED , vid . activeapp ) ;
return true ;
}
static void D3D11_DoResize ( void )
{
d3d_resized = true ;
D3DVID_UpdateWindowStatus ( mainwindow ) ;
if ( d3dscreen )
{ //seriously? this is disgusting.
DXGI_OUTPUT_DESC desc ;
IDXGIOutput_GetDesc ( d3dscreen , & desc ) ;
vid . pixelwidth = desc . DesktopCoordinates . right - desc . DesktopCoordinates . left ;
vid . pixelheight = desc . DesktopCoordinates . bottom - desc . DesktopCoordinates . top ;
}
else
{
vid . pixelwidth = window_rect . right - window_rect . left ;
vid . pixelheight = window_rect . bottom - window_rect . top ;
}
// Con_Printf("Resizing buffer to %i*%i\n", vid.pixelwidth, vid.pixelheight);
released3dbackbuffer ( ) ;
IDXGISwapChain_ResizeBuffers ( d3dswapchain , 0 , vid . pixelwidth , vid . pixelheight , DXGI_FORMAT_UNKNOWN , DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ) ;
D3D11BE_Reset ( true ) ;
resetd3dbackbuffer ( vid . pixelwidth , vid . pixelheight ) ;
D3D11BE_Reset ( false ) ;
}
static LRESULT WINAPI D3D11_WindowProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
LONG lRet = 0 ;
int fActive , fMinimized , temp ;
extern unsigned int uiWheelMessage ;
extern qboolean keydown [ K_MAX ] ;
if ( uMsg = = uiWheelMessage )
uMsg = WM_MOUSEWHEEL ;
switch ( uMsg )
{
# if 1
/* case WM_KILLFOCUS:
if ( modestate = = MS_FULLDIB )
ShowWindow ( mainwindow , SW_SHOWMINNOACTIVE ) ;
break ;
*/
// case WM_CREATE:
// break;
case WM_MOVE :
D3DVID_UpdateWindowStatus ( hWnd ) ;
lRet = DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
break ;
case WM_KEYDOWN :
case WM_SYSKEYDOWN :
if ( keydown [ K_LALT ] & & wParam = = ' \r ' )
{
if ( d3dscreen )
{
IDXGIOutput_Release ( d3dscreen ) ;
d3dscreen = NULL ;
}
if ( modestate = = MS_FULLSCREEN )
modestate = MS_WINDOWED ;
else
{
RECT rect ;
extern cvar_t vid_width , vid_height ;
int width = vid_width . ival ;
int height = vid_height . ival ;
if ( ! width | | ! height )
{
DXGI_OUTPUT_DESC desc ;
IDXGISwapChain_GetContainingOutput ( d3dswapchain , & d3dscreen ) ;
IDXGIOutput_GetDesc ( d3dscreen , & desc ) ;
rect = desc . DesktopCoordinates ;
}
else
{
rect . left = ( GetSystemMetrics ( SM_CXSCREEN ) - width ) / 2 ;
rect . top = ( GetSystemMetrics ( SM_CYSCREEN ) - height ) / 2 ;
rect . right = rect . left + width ;
rect . bottom = rect . top + height ;
}
AdjustWindowRectEx ( & rect , WS_OVERLAPPED , FALSE , 0 ) ;
SetWindowPos ( hWnd , NULL , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , SWP_SHOWWINDOW | SWP_FRAMECHANGED ) ;
modestate = MS_FULLSCREEN ;
}
2016-12-13 11:50:15 +00:00
2016-07-12 00:40:13 +00:00
if ( ! d3dscreen & & modestate = = MS_FULLSCREEN )
IDXGISwapChain_GetContainingOutput ( d3dswapchain , & d3dscreen ) ;
IDXGISwapChain_SetFullscreenState ( d3dswapchain , modestate = = MS_FULLSCREEN , ( modestate = = MS_FULLSCREEN ) ? d3dscreen : NULL ) ;
if ( modestate = = MS_WINDOWED )
{
RECT rect ;
int width = 640 ;
int height = 480 ;
rect . left = ( GetSystemMetrics ( SM_CXSCREEN ) - width ) / 2 ;
rect . top = ( GetSystemMetrics ( SM_CYSCREEN ) - height ) / 2 ;
rect . right = rect . left + width ;
rect . bottom = rect . top + height ;
AdjustWindowRectEx ( & rect , WS_OVERLAPPEDWINDOW , FALSE , 0 ) ;
SetWindowLong ( hWnd , GWL_STYLE , WS_OVERLAPPEDWINDOW ) ; //make sure dxgi didn't break us.
SetWindowPos ( hWnd , HWND_TOP , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , SWP_SHOWWINDOW | SWP_FRAMECHANGED ) ;
SetForegroundWindow ( hWnd ) ;
SetFocus ( hWnd ) ;
//work around a windows bug by forcing all windows to be repainted.
InvalidateRect ( NULL , NULL , false ) ;
}
D3D11_DoResize ( ) ;
Cvar_ForceCallback ( & v_gamma ) ;
}
else if ( ! vid_initializing )
INS_TranslateKeyEvent ( wParam , lParam , true , 0 , false ) ;
break ;
case WM_KEYUP :
case WM_SYSKEYUP :
if ( ! vid_initializing )
INS_TranslateKeyEvent ( wParam , lParam , false , 0 , false ) ;
break ;
2017-06-21 01:24:25 +00:00
case WM_APPCOMMAND :
lRet = INS_AppCommand ( lParam ) ;
break ;
2016-07-12 00:40:13 +00:00
case WM_SYSCHAR :
// keep Alt-Space from happening
break ;
// this is complicated because Win32 seems to pack multiple mouse events into
// one update sometimes, so we always check all states and look for events
case WM_LBUTTONDOWN :
case WM_LBUTTONUP :
case WM_RBUTTONDOWN :
case WM_RBUTTONUP :
case WM_MBUTTONDOWN :
case WM_MBUTTONUP :
case WM_MOUSEMOVE :
case WM_XBUTTONDOWN :
case WM_XBUTTONUP :
temp = 0 ;
if ( wParam & MK_LBUTTON )
temp | = 1 ;
if ( wParam & MK_RBUTTON )
temp | = 2 ;
if ( wParam & MK_MBUTTON )
temp | = 4 ;
if ( wParam & MK_XBUTTON1 )
temp | = 8 ;
if ( wParam & MK_XBUTTON2 )
temp | = 16 ;
if ( wParam & MK_XBUTTON3 )
temp | = 32 ;
if ( wParam & MK_XBUTTON4 )
temp | = 64 ;
if ( wParam & MK_XBUTTON5 )
temp | = 128 ;
if ( wParam & MK_XBUTTON6 )
temp | = 256 ;
if ( wParam & MK_XBUTTON7 )
temp | = 512 ;
if ( ! vid_initializing )
INS_MouseEvent ( temp ) ;
break ;
// JACK: This is the mouse wheel with the Intellimouse
// Its delta is either positive or neg, and we generate the proper
// Event.
case WM_MOUSEWHEEL :
if ( ! vid_initializing )
{
if ( ( short ) HIWORD ( wParam ) > 0 )
{
Key_Event ( 0 , K_MWHEELUP , 0 , true ) ;
Key_Event ( 0 , K_MWHEELUP , 0 , false ) ;
}
else
{
Key_Event ( 0 , K_MWHEELDOWN , 0 , true ) ;
Key_Event ( 0 , K_MWHEELDOWN , 0 , false ) ;
}
}
break ;
case WM_INPUT :
// raw input handling
if ( ! vid_initializing )
INS_RawInput_Read ( ( HANDLE ) lParam ) ;
break ;
case WM_SETCURSOR :
//only use a custom cursor if the cursor is inside the client area
switch ( lParam & 0xffff )
{
case 0 :
break ;
case HTCLIENT :
if ( hCustomCursor ) //custom cursor enabled
SetCursor ( hCustomCursor ) ;
else //fallback on an arrow cursor, just so we have something visible at startup or so
SetCursor ( hArrowCursor ) ;
lRet = TRUE ;
break ;
default :
lRet = DefWindowProcW ( hWnd , uMsg , wParam , lParam ) ;
break ;
}
break ;
case WM_GETMINMAXINFO :
{
RECT windowrect ;
RECT clientrect ;
MINMAXINFO * mmi = ( MINMAXINFO * ) lParam ;
GetWindowRect ( hWnd , & windowrect ) ;
GetClientRect ( hWnd , & clientrect ) ;
mmi - > ptMinTrackSize . x = 320 + ( ( windowrect . right - windowrect . left ) - ( clientrect . right - clientrect . left ) ) ;
mmi - > ptMinTrackSize . y = 200 + ( ( windowrect . bottom - windowrect . top ) - ( clientrect . bottom - clientrect . top ) ) ;
}
return 0 ;
2017-02-21 20:22:07 +00:00
case WM_SIZE :
2016-07-12 00:40:13 +00:00
d3d_resized = true ;
D3DVID_UpdateWindowStatus ( mainwindow ) ;
released3dbackbuffer ( ) ;
IDXGISwapChain_ResizeBuffers ( d3dswapchain , 0 , 0 , 0 , DXGI_FORMAT_UNKNOWN , DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ) ;
D3D11BE_Reset ( true ) ;
vid . pixelwidth = window_rect . right - window_rect . left ;
vid . pixelheight = window_rect . bottom - window_rect . top ;
resetd3dbackbuffer ( vid . pixelwidth , vid . pixelheight ) ;
D3D11BE_Reset ( false ) ;
lRet = DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
break ;
case WM_CLOSE :
if ( ! vid_initializing )
if ( MessageBox ( mainwindow , " Are you sure you want to quit? " , " Confirm Exit " ,
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION ) = = IDYES )
{
Cbuf_AddText ( " \n quit \n " , RESTRICT_LOCAL ) ;
}
2016-07-21 19:27:59 +00:00
break ;
2016-07-12 00:40:13 +00:00
case WM_ACTIVATE :
fActive = LOWORD ( wParam ) ;
fMinimized = ( BOOL ) HIWORD ( wParam ) ;
if ( ! D3D11AppActivate ( ! ( fActive = = WA_INACTIVE ) , fMinimized ) )
break ; //so, urm, tell me microsoft, what changed?
if ( modestate = = MS_FULLDIB )
ShowWindow ( mainwindow , SW_SHOWNORMAL ) ;
if ( modestate = = MS_FULLSCREEN )
{
2016-07-21 19:27:59 +00:00
if ( d3dswapchain )
{
IDXGISwapChain_SetFullscreenState ( d3dswapchain , vid . activeapp , d3dscreen ) ;
D3D11_DoResize ( ) ;
}
2016-07-12 00:40:13 +00:00
}
Cvar_ForceCallback ( & v_gamma ) ;
// fix the leftover Alt from any Alt-Tab or the like that switched us away
// ClearAllStates ();
lRet = 1 ;
break ;
2017-02-21 20:22:07 +00:00
case WM_DESTROY :
{
2016-07-12 00:40:13 +00:00
// if (dibwindow)
// DestroyWindow (dibwindow);
2017-02-21 20:22:07 +00:00
}
break ;
# ifdef HAVE_CDPLAYER
2016-07-12 00:40:13 +00:00
case MM_MCINOTIFY :
2017-02-21 20:22:07 +00:00
lRet = CDAudio_MessageHandler ( hWnd , uMsg , wParam , lParam ) ;
2016-07-12 00:40:13 +00:00
break ;
2017-02-21 20:22:07 +00:00
# endif
2016-07-12 00:40:13 +00:00
# endif
case WM_ERASEBKGND :
return 1 ;
2017-02-21 20:22:07 +00:00
default :
/* pass all unhandled messages to DefWindowProc */
lRet = DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
break ;
}
/* return 1 if handled message, 0 if not */
return lRet ;
2016-07-12 00:40:13 +00:00
}
# endif
# if (WINVER < 0x500) && !defined(__GNUC__)
typedef struct tagMONITORINFO
{
2017-02-21 20:22:07 +00:00
DWORD cbSize ;
RECT rcMonitor ;
RECT rcWork ;
DWORD dwFlags ;
2016-07-12 00:40:13 +00:00
} MONITORINFO , * LPMONITORINFO ;
# endif
static void released3dbackbuffer ( void )
{
if ( d3ddevctx )
ID3D11DeviceContext_OMSetRenderTargets ( d3ddevctx , 0 , NULL , NULL ) ;
if ( fb_backbuffer )
ID3D11RenderTargetView_Release ( fb_backbuffer ) ;
fb_backbuffer = NULL ;
if ( fb_backdepthstencil )
ID3D11DepthStencilView_Release ( fb_backdepthstencil ) ;
fb_backdepthstencil = NULL ;
}
static qboolean resetd3dbackbuffer ( int width , int height )
{
D3D11_TEXTURE2D_DESC t2ddesc ;
// D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ID3D11Texture2D * backbuftex , * depthtex ;
released3dbackbuffer ( ) ;
//get a proper handle to the backbuffer (silly hurdles)
if ( FAILED ( IDXGISwapChain_GetBuffer ( d3dswapchain , 0 , & qIID_ID3D11Texture2D , ( LPVOID * ) & backbuftex ) ) )
return false ;
if ( FAILED ( ID3D11Device_CreateRenderTargetView ( pD3DDev11 , ( ID3D11Resource * ) backbuftex , NULL , & fb_backbuffer ) ) )
return false ;
ID3D11Texture2D_Release ( backbuftex ) ;
//set up a depth buffer.
memset ( & t2ddesc , 0 , sizeof ( t2ddesc ) ) ;
t2ddesc . Width = width ;
t2ddesc . Height = height ;
t2ddesc . MipLevels = 1 ;
t2ddesc . ArraySize = 1 ;
t2ddesc . Format = DXGI_FORMAT_D24_UNORM_S8_UINT ;
t2ddesc . SampleDesc . Count = d3d11multisample_count ;
t2ddesc . SampleDesc . Quality = d3d11multisample_quality ;
t2ddesc . Usage = D3D11_USAGE_DEFAULT ;
t2ddesc . BindFlags = D3D11_BIND_DEPTH_STENCIL ;
t2ddesc . CPUAccessFlags = 0 ;
t2ddesc . MiscFlags = 0 ;
if ( FAILED ( ID3D11Device_CreateTexture2D ( pD3DDev11 , & t2ddesc , NULL , & depthtex ) ) )
return false ;
// dsvd.Format = t2ddesc.Format;
// dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
// dsvd.Texture2D.MipSlice = 0;
if ( FAILED ( ID3D11Device_CreateDepthStencilView ( pD3DDev11 , ( ID3D11Resource * ) depthtex , NULL /*&dsvd*/ , & fb_backdepthstencil ) ) )
return false ;
ID3D11Texture2D_Release ( depthtex ) ;
//now tell d3d which render targets to use.
ID3D11DeviceContext_OMSetRenderTargets ( d3ddevctx , 1 , & fb_backbuffer , fb_backdepthstencil ) ;
return true ;
}
# ifdef WINRT //winrt crap has its own non-hwnd window crap, after years of microsoft forcing everyone to use hwnds for everything. I wonder why they don't have that many winrt apps.
void D3D11_DoResize ( int newwidth , int newheight )
{
d3d_resized = true ;
// Con_Printf("Resizing buffer to %i*%i\n", vid.pixelwidth, vid.pixelheight);
released3dbackbuffer ( ) ;
if ( d3dswapchain )
{
IDXGISwapChain_ResizeBuffers ( d3dswapchain , 0 , vid . pixelwidth , vid . pixelheight , DXGI_FORMAT_UNKNOWN , DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ) ;
D3D11BE_Reset ( true ) ;
resetd3dbackbuffer ( vid . pixelwidth , vid . pixelheight ) ;
D3D11BE_Reset ( false ) ;
}
}
void * RT_GetCoreWindow ( int * width , int * height ) ;
static qboolean D3D11_VID_Init ( rendererstate_t * info , unsigned char * palette )
{
static IID factiid1 = { 0x770aae78 , 0xf26f , 0x4dba , 0xa8 , 0x29 , 0x25 , 0x3c , 0x83 , 0xd1 , 0xb3 , 0x87 } ;
static IID factiid2 = { 0x50c83a1c , 0xe072 , 0x4c48 , 0x87 , 0xb0 , 0x36 , 0x30 , 0xfa , 0x36 , 0xa6 , 0xd0 } ;
IDXGIFactory2 * fact = NULL ;
HRESULT hr ;
D3D_FEATURE_LEVEL flevel , flevels [ ] =
{
//D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0 ,
D3D_FEATURE_LEVEL_10_1 ,
D3D_FEATURE_LEVEL_10_0 ,
D3D_FEATURE_LEVEL_9_3 ,
D3D_FEATURE_LEVEL_9_2 ,
D3D_FEATURE_LEVEL_9_1
} ;
DXGI_SWAP_CHAIN_DESC1 scd = { 0 } ;
IUnknown * window = RT_GetCoreWindow ( & info - > width , & info - > height ) ;
modestate = MS_FULLSCREEN ;
//fill scd
scd . Width = info - > width ;
scd . Height = info - > height ;
scd . Format = info - > srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_B8G8R8A8_UNORM ;
scd . Stereo = info - > stereo ;
scd . SampleDesc . Count = d3d11multisample_count = max ( 1 , info - > multisample ) ;
scd . SampleDesc . Quality = d3d11multisample_quality = ( d3d11multisample_count > 1 ) ? ~ 0 : 0 ;
scd . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
scd . BufferCount = 2 + info - > triplebuffer ; //rt only supports fullscreen, so the frontbuffer needs to be created by us.
scd . SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL ;
scd . Flags = 0 ;
//create d3d stuff
hr = CreateDXGIFactory1 ( & factiid2 , & fact ) ;
if ( FAILED ( D3D11CreateDevice ( NULL , D3D_DRIVER_TYPE_HARDWARE , NULL , 0 , flevels , sizeof ( flevels ) / sizeof ( flevels [ 0 ] ) , D3D11_SDK_VERSION , & pD3DDev11 , & flevel , & d3ddevctx ) ) )
Sys_Error ( " D3D11CreateDevice failed \n " ) ;
else
{
if ( FAILED ( IDXGIFactory2_CreateSwapChainForCoreWindow ( fact , ( IUnknown * ) pD3DDev11 , window , & scd , NULL , & d3dswapchain ) ) )
Sys_Error ( " IDXGIFactory2_CreateSwapChainForCoreWindow failed \n " ) ;
else
{
vid . numpages = scd . BufferCount ;
if ( ! resetd3dbackbuffer ( info - > width , info - > height ) )
Sys_Error ( " unable to reset back buffer \n " ) ;
else
{
if ( ! D3D11Shader_Init ( flevel ) )
Con_Printf ( " Unable to intialise a suitable HLSL compiler, please install the DirectX runtime. \n " ) ;
else
return true ;
}
}
}
return false ;
}
# else
static qboolean initD3D11Device ( HWND hWnd , rendererstate_t * info , PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func , IDXGIAdapter * adapt )
{
UINT support ;
int flags = 0 ; //= D3D11_CREATE_DEVICE_SINGLETHREADED;
D3D_DRIVER_TYPE drivertype ;
DXGI_SWAP_CHAIN_DESC scd ;
D3D_FEATURE_LEVEL flevel , flevels [ ] =
{
//D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0 ,
D3D_FEATURE_LEVEL_10_1 ,
D3D_FEATURE_LEVEL_10_0 ,
//FIXME: need npot.
D3D_FEATURE_LEVEL_9_3 ,
D3D_FEATURE_LEVEL_9_2 ,
D3D_FEATURE_LEVEL_9_1
} ;
memset ( & scd , 0 , sizeof ( scd ) ) ;
if ( ! stricmp ( info - > subrenderer , " debug " ) )
flags | = D3D11_CREATE_DEVICE_DEBUG ;
if ( ! stricmp ( info - > subrenderer , " warp " ) )
drivertype = D3D_DRIVER_TYPE_WARP ;
else if ( ! stricmp ( info - > subrenderer , " ref " ) )
drivertype = D3D_DRIVER_TYPE_REFERENCE ;
else if ( ! stricmp ( info - > subrenderer , " hw " ) )
drivertype = D3D_DRIVER_TYPE_HARDWARE ;
else if ( ! stricmp ( info - > subrenderer , " null " ) )
drivertype = D3D_DRIVER_TYPE_NULL ;
else if ( ! stricmp ( info - > subrenderer , " software " ) )
drivertype = D3D_DRIVER_TYPE_SOFTWARE ;
else if ( ! stricmp ( info - > subrenderer , " unknown " ) )
drivertype = D3D_DRIVER_TYPE_UNKNOWN ;
else
drivertype = adapt ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE ;
//for stereo support, we would have to rewrite all of this in a way that would make us dependant upon windows 8 or 7+platform update, which would exclude vista.
scd . BufferDesc . Width = info - > width ;
scd . BufferDesc . Height = info - > height ;
scd . BufferDesc . RefreshRate . Numerator = 0 ;
scd . BufferDesc . RefreshRate . Denominator = 0 ;
scd . BufferCount = 1 + info - > triplebuffer ; //back buffer count
scd . BufferDesc . Format = info - > srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM ; //32bit colour
scd . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
scd . OutputWindow = hWnd ;
scd . SampleDesc . Count = d3d11multisample_count = max ( 1 , info - > multisample ) ; //as we're starting up windowed (and switching to fullscreen after), the frontbuffer is handled by windows.
scd . SampleDesc . Quality = d3d11multisample_quality = 0 ;
scd . Windowed = TRUE ;
scd . Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ; // | DXGI_SWAP_CHAIN_FLAG_NONPREROTATED;
# ifdef _DEBUG
// flags |= D3D11_CREATE_DEVICE_DEBUG;
# endif
if ( drivertype = = D3D_DRIVER_TYPE_UNKNOWN & & adapt )
{
DXGI_ADAPTER_DESC adesc ;
IDXGIAdapter_GetDesc ( adapt , & adesc ) ;
Con_Printf ( " D3D11 Adaptor: %S \n " , adesc . Description ) ;
}
else
adapt = NULL ;
if ( FAILED ( func ( adapt , drivertype , NULL , flags ,
flevels , sizeof ( flevels ) / sizeof ( flevels [ 0 ] ) ,
D3D11_SDK_VERSION ,
& scd ,
& d3dswapchain ,
& pD3DDev11 ,
& flevel ,
& d3ddevctx ) ) )
return false ;
if ( ! pD3DDev11 )
return false ;
Con_Printf ( " D3D11 Feature level: %i_%i \n " , flevel > > 12 , ( flevel > > 8 ) & 0xf ) ;
if ( ! resetd3dbackbuffer ( info - > width , info - > height ) )
return false ;
if ( info - > fullscreen )
{
}
memset ( & sh_config , 0 , sizeof ( sh_config ) ) ;
sh_config . texture_non_power_of_two = flevel > = D3D_FEATURE_LEVEL_10_0 ; //npot MUST be supported on all d3d10+ cards.
sh_config . texture_non_power_of_two_pic = true ; //always supported in d3d11, supposedly, even with d3d9 devices.
sh_config . npot_rounddown = false ;
if ( flevel > = D3D_FEATURE_LEVEL_11_0 )
sh_config . texture_maxsize = 16384 ;
else if ( flevel > = D3D_FEATURE_LEVEL_10_0 )
sh_config . texture_maxsize = 8192 ;
else if ( flevel > = D3D_FEATURE_LEVEL_9_3 )
sh_config . texture_maxsize = 4096 ;
else
sh_config . texture_maxsize = 2048 ;
//11.1 formats
# define DXGI_FORMAT_B4G4R4A4_UNORM 115
2017-07-12 08:15:27 +00:00
//why does d3d11 have no rgbx format? anyone else think that weird?
2016-07-12 00:40:13 +00:00
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B5G6R5_UNORM , & support ) ; sh_config . texfmt [ PTI_RGB565 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B5G5R5A1_UNORM , & support ) ; sh_config . texfmt [ PTI_ARGB1555 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B4G4R4A4_UNORM , & support ) ; sh_config . texfmt [ PTI_ARGB4444 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_R8G8B8A8_UNORM , & support ) ; sh_config . texfmt [ PTI_RGBA8 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B8G8R8A8_UNORM , & support ) ; sh_config . texfmt [ PTI_BGRA8 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B8G8R8X8_UNORM , & support ) ; sh_config . texfmt [ PTI_BGRX8 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
2017-07-12 08:15:27 +00:00
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_R8G8B8A8_UNORM_SRGB , & support ) ; sh_config . texfmt [ PTI_RGBA8_SRGB ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B8G8R8A8_UNORM_SRGB , & support ) ; sh_config . texfmt [ PTI_BGRA8_SRGB ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_B8G8R8X8_UNORM_SRGB , & support ) ; sh_config . texfmt [ PTI_BGRX8_SRGB ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
2016-07-12 00:40:13 +00:00
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_BC1_UNORM , & support ) ; sh_config . texfmt [ PTI_S3RGBA1 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_BC2_UNORM , & support ) ; sh_config . texfmt [ PTI_S3RGBA3 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
ID3D11Device_CheckFormatSupport ( pD3DDev11 , DXGI_FORMAT_BC3_UNORM , & support ) ; sh_config . texfmt [ PTI_S3RGBA5 ] = ! ! ( support & D3D11_FORMAT_SUPPORT_TEXTURE2D ) ;
//these formats are not officially supported as specified, but noone cares
sh_config . texfmt [ PTI_RGBX8 ] = sh_config . texfmt [ PTI_RGBA8 ] ;
sh_config . texfmt [ PTI_S3RGB1 ] = sh_config . texfmt [ PTI_S3RGBA1 ] ;
2017-07-12 08:15:27 +00:00
vid . srgb = info - > srgb > 1 ;
2016-07-12 00:40:13 +00:00
vid . numpages = scd . BufferCount ;
if ( ! D3D11Shader_Init ( flevel ) )
{
Con_Printf ( " Unable to intialise a suitable HLSL compiler, please install the DirectX runtime. \n " ) ;
return false ;
}
return true ;
}
static void initD3D11 ( HWND hWnd , rendererstate_t * info )
{
static dllhandle_t * dxgi ;
static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN fnc ;
static HRESULT ( WINAPI * pCreateDXGIFactory1 ) ( IID * riid , void * * ppFactory ) ;
static IID factiid = { 0x770aae78 , 0xf26f , 0x4dba , { 0xa8 , 0x29 , 0x25 , 0x3c , 0x83 , 0xd1 , 0xb3 , 0x87 } } ;
IDXGIFactory1 * fact = NULL ;
IDXGIAdapter * adapt = NULL ;
dllfunction_t d3d11funcs [ ] =
{
{ ( void * * ) & fnc , " D3D11CreateDeviceAndSwapChain " } ,
{ NULL }
} ;
dllfunction_t dxgifuncs [ ] =
{
{ ( void * * ) & pCreateDXGIFactory1 , " CreateDXGIFactory1 " } ,
{ NULL }
} ;
if ( ! dxgi )
dxgi = Sys_LoadLibrary ( " dxgi " , dxgifuncs ) ;
if ( ! d3d11mod )
d3d11mod = Sys_LoadLibrary ( " d3d11 " , d3d11funcs ) ;
if ( ! d3d11mod )
return ;
if ( pCreateDXGIFactory1 )
{
HRESULT hr ;
hr = pCreateDXGIFactory1 ( & factiid , ( void * * ) & fact ) ;
if ( FAILED ( hr ) )
Con_Printf ( " CreateDXGIFactory1 failed: %s \n " , D3D_NameForResult ( hr ) ) ;
if ( fact )
{
IDXGIFactory1_EnumAdapters ( fact , 0 , & adapt ) ;
}
}
initD3D11Device ( hWnd , info , fnc , adapt ) ;
if ( adapt )
IDXGIAdapter_Release ( adapt ) ;
if ( fact )
{
//DXGI SUCKS and fucks up alt+tab every single time. its pointless to go from fullscreen to fullscreen-with-taskbar-obscuring-half-the-window.
//I'm just going to handle that stuff myself.
IDXGIFactory1_MakeWindowAssociation ( fact , hWnd , DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_PRINT_SCREEN ) ;
IDXGIFactory1_Release ( fact ) ;
}
}
static qboolean D3D11_VID_Init ( rendererstate_t * info , unsigned char * palette )
{
DWORD width = info - > width ;
DWORD height = info - > height ;
//DWORD bpp = info->bpp;
//DWORD zbpp = 16;
//DWORD flags = 0;
DWORD wstyle ;
RECT rect ;
MSG msg ;
//DDGAMMARAMP gammaramp;
//int i;
char * CLASSNAME = " FTED3D11QUAKE " ;
WNDCLASS wc = {
0 ,
& D3D11_WindowProc ,
0 ,
0 ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
CLASSNAME
} ;
wc . style = CS_HREDRAW | CS_VREDRAW ;
wc . hCursor = hArrowCursor = LoadCursor ( NULL , IDC_ARROW ) ;
wc . hInstance = global_hInstance ;
vid_initializing = true ;
RegisterClass ( & wc ) ;
modestate = info - > fullscreen ? MS_FULLSCREEN : MS_WINDOWED ;
wstyle = WS_OVERLAPPEDWINDOW ;
rect . left = ( GetSystemMetrics ( SM_CXSCREEN ) - width ) / 2 ;
rect . top = ( GetSystemMetrics ( SM_CYSCREEN ) - height ) / 2 ;
rect . right = rect . left + width ;
rect . bottom = rect . top + height ;
AdjustWindowRectEx ( & rect , wstyle , FALSE , 0 ) ;
mainwindow = CreateWindow ( CLASSNAME , " Direct3D11 " , wstyle , rect . left , rect . top , rect . right - rect . left , rect . bottom - rect . top , NULL , NULL , NULL , NULL ) ;
// Try as specified.
DoDXGIDebug ( ) ;
initD3D11 ( mainwindow , info ) ;
if ( ! pD3DDev11 )
{
DoDXGIDebug ( ) ;
Con_Printf ( " No suitable D3D11 device found \n " ) ;
return false ;
}
if ( info - > fullscreen )
{
if ( ! d3dscreen )
IDXGISwapChain_GetContainingOutput ( d3dswapchain , & d3dscreen ) ;
IDXGISwapChain_SetFullscreenState ( d3dswapchain , true , d3dscreen ) ;
}
vid . pixelwidth = width ;
vid . pixelheight = height ;
while ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) )
{
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
CL_UpdateWindowTitle ( ) ;
ShowWindow ( mainwindow , SW_SHOWNORMAL ) ;
vid . width = vid . pixelwidth ;
vid . height = vid . pixelheight ;
vid_initializing = false ;
GetWindowRect ( mainwindow , & window_rect ) ;
{
extern qboolean mouseactive ;
mouseactive = false ;
}
rf - > VID_CreateCursor = WIN_CreateCursor ;
rf - > VID_DestroyCursor = WIN_DestroyCursor ;
rf - > VID_SetCursor = WIN_SetCursor ;
return true ;
}
# endif
static void ( D3D11_VID_DeInit ) ( void )
{
Image_Shutdown ( ) ;
/*we cannot shut down cleanly while in fullscreen, supposedly*/
if ( d3dswapchain )
IDXGISwapChain_SetFullscreenState ( d3dswapchain , false , NULL ) ;
released3dbackbuffer ( ) ;
if ( d3dswapchain )
IDXGISwapChain_Release ( d3dswapchain ) ;
d3dswapchain = NULL ;
if ( pD3DDev11 )
ID3D11Device_Release ( pD3DDev11 ) ;
pD3DDev11 = NULL ;
if ( d3ddevctx )
{
ID3D11DeviceContext_ClearState ( d3ddevctx ) ;
ID3D11DeviceContext_Flush ( d3ddevctx ) ;
ID3D11DeviceContext_Release ( d3ddevctx ) ;
}
d3ddevctx = NULL ;
# ifndef WINRT
if ( mainwindow )
{
DestroyWindow ( mainwindow ) ;
mainwindow = NULL ;
}
# endif
if ( d3dscreen )
IUnknown_Release ( d3dscreen ) ;
d3dscreen = NULL ;
DoDXGIDebug ( ) ;
}
extern float hw_blend [ 4 ] ; // rgba 0.0 - 1.0
static void D3D11_BuildRamps ( int points , DXGI_RGB * out )
{
2016-07-28 15:57:22 +00:00
//FIXME: repack input rather than recalculating.
2016-07-12 00:40:13 +00:00
int i ;
vec3_t cshift ;
vec3_t c ;
float sc ;
VectorScale ( hw_blend , hw_blend [ 3 ] , cshift ) ;
for ( i = 0 ; i < points ; i + + )
{
sc = i / ( float ) ( points - 1 ) ;
VectorSet ( c , sc , sc , sc ) ;
VectorAdd ( c , cshift , c ) ;
VectorScale ( c , v_contrast . value , c ) ;
out [ i ] . Red = pow ( c [ 0 ] , v_gamma . value ) + v_brightness . value ;
out [ i ] . Green = pow ( c [ 1 ] , v_gamma . value ) + v_brightness . value ;
out [ i ] . Blue = pow ( c [ 2 ] , v_gamma . value ) + v_brightness . value ;
}
}
2016-07-28 15:57:22 +00:00
static qboolean D3D11_VID_ApplyGammaRamps ( unsigned int gammarampsize , unsigned short * ramps )
2016-07-12 00:40:13 +00:00
{
HRESULT hr ;
DXGI_GAMMA_CONTROL_CAPABILITIES caps ;
DXGI_GAMMA_CONTROL gam ;
//cache the screen, so we don't get too confused.
if ( ! d3dscreen )
return false ; //don't do it when we're running windowed.
if ( d3dscreen )
{
gam . Scale . Red = 1 ;
gam . Scale . Green = 1 ;
gam . Scale . Blue = 1 ;
gam . Offset . Red = 0 ;
gam . Offset . Green = 0 ;
gam . Offset . Blue = 0 ;
if ( FAILED ( IDXGIOutput_GetGammaControlCapabilities ( d3dscreen , & caps ) ) )
return false ;
if ( caps . NumGammaControlPoints > 1025 )
caps . NumGammaControlPoints = 1025 ;
D3D11_BuildRamps ( caps . NumGammaControlPoints , gam . GammaCurve ) ;
hr = IDXGIOutput_SetGammaControl ( d3dscreen , & gam ) ;
if ( SUCCEEDED ( hr ) )
return true ;
}
return false ;
}
2017-05-10 03:13:18 +00:00
static char * D3D11_VID_GetRGBInfo ( int * bytestride , int * truevidwidth , int * truevidheight , enum uploadfmt * fmt )
2016-07-12 00:40:13 +00:00
{
//don't directly map the frontbuffer, as that can hold other things.
//create a texture, copy the (gpu)backbuffer to that (cpu)texture
//then map the (cpu)texture and copy out the parts we need, reordering as needed.
D3D11_MAPPED_SUBRESOURCE lock ;
qbyte * rgb , * in , * r = NULL ;
unsigned int x , y ;
D3D11_TEXTURE2D_DESC texDesc ;
ID3D11Texture2D * texture ;
ID3D11Resource * backbuffer ;
texDesc . ArraySize = 1 ;
texDesc . BindFlags = 0 ;
texDesc . CPUAccessFlags = 0 ;
texDesc . Format = DXGI_FORMAT_R8G8B8A8_UNORM ;
texDesc . Width = vid . pixelwidth ;
texDesc . Height = vid . pixelheight ;
texDesc . MipLevels = 1 ;
texDesc . MiscFlags = 0 ;
texDesc . SampleDesc . Count = 1 ;
texDesc . SampleDesc . Quality = 0 ;
texDesc . Usage = D3D11_USAGE_STAGING ;
texDesc . CPUAccessFlags = D3D11_CPU_ACCESS_READ ;
if ( FAILED ( ID3D11Device_CreateTexture2D ( pD3DDev11 , & texDesc , 0 , & texture ) ) )
return NULL ;
ID3D11RenderTargetView_GetResource ( fb_backbuffer , & backbuffer ) ;
ID3D11DeviceContext_CopyResource ( d3ddevctx , ( ID3D11Resource * ) texture , backbuffer ) ;
ID3D11Resource_Release ( backbuffer ) ;
if ( ! FAILED ( ID3D11DeviceContext_Map ( d3ddevctx , ( ID3D11Resource * ) texture , 0 , D3D11_MAP_READ , 0 , & lock ) ) )
{
r = rgb = BZ_Malloc ( 3 * vid . pixelwidth * vid . pixelheight ) ;
for ( y = vid . pixelheight ; y - - > 0 ; )
{
in = lock . pData ;
in + = y * lock . RowPitch ;
for ( x = 0 ; x < vid . pixelwidth ; x + + , rgb + = 3 , in + = 4 )
{
rgb [ 0 ] = in [ 0 ] ;
rgb [ 1 ] = in [ 1 ] ;
rgb [ 2 ] = in [ 2 ] ;
}
}
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) texture , 0 ) ;
}
ID3D11Texture2D_Release ( texture ) ;
2017-05-10 03:13:18 +00:00
* bytestride = vid . pixelwidth * 3 ;
2016-07-12 00:40:13 +00:00
* truevidwidth = vid . pixelwidth ;
* truevidheight = vid . pixelheight ;
* fmt = TF_RGB24 ;
return r ;
}
static void ( D3D11_VID_SetWindowCaption ) ( const char * msg )
{
# ifndef WINRT
SetWindowText ( mainwindow , msg ) ;
# endif
}
void D3D11_Set2D ( void )
{
D3D11_VIEWPORT vport ;
// Matrix4x4_CM_Orthographic(r_refdef.m_projection, 0 + (0.5*vid.width/vid.pixelwidth), vid.width + (0.5*vid.width/vid.pixelwidth), 0 + (0.5*vid.height/vid.pixelheight), vid.height + (0.5*vid.height/vid.pixelheight), 0, 100);
Matrix4x4_CM_Orthographic ( r_refdef . m_projection , 0 , vid . width , vid . height , 0 , 0 , 99999 ) ;
Matrix4x4_Identity ( r_refdef . m_view ) ;
vport . TopLeftX = 0 ;
vport . TopLeftY = 0 ;
vport . Width = vid . pixelwidth ;
vport . Height = vid . pixelheight ;
vport . MinDepth = 0 ;
vport . MaxDepth = 1 ;
ID3D11DeviceContext_RSSetViewports ( d3ddevctx , 1 , & vport ) ;
D3D11BE_SetupViewCBuffer ( ) ;
vid . fbvwidth = vid . width ;
vid . fbvheight = vid . height ;
vid . fbpwidth = vid . pixelwidth ;
vid . fbpheight = vid . pixelheight ;
D3D11BE_Scissor ( NULL ) ;
r_refdef . pxrect . x = 0 ;
r_refdef . pxrect . y = 0 ;
r_refdef . pxrect . width = vid . fbpwidth ;
r_refdef . pxrect . height = vid . fbpheight ;
}
static qboolean ( D3D11_SCR_UpdateScreen ) ( void )
{
//extern int keydown[];
//extern cvar_t vid_conheight;
int uimenu ;
# ifdef TEXTEDITOR
//extern qboolean editormodal;
# endif
qboolean nohud , noworld ;
if ( r_clear . ival )
{
float colours [ 4 ] = { ( r_clear . ival & 1 ) ? 1 : 0 , ( r_clear . ival & 2 ) ? 1 : 0 , ( r_clear . ival & 4 ) ? 1 : 0 , 1 } ;
ID3D11DeviceContext_ClearRenderTargetView ( d3ddevctx , fb_backbuffer , colours ) ;
}
if ( d3d_resized )
{
extern cvar_t vid_conautoscale , vid_conwidth ;
d3d_resized = false ;
// force width/height to be updated
//vid.pixelwidth = window_rect.right - window_rect.left;
//vid.pixelheight = window_rect.bottom - window_rect.top;
Cvar_ForceCallback ( & vid_conautoscale ) ;
Cvar_ForceCallback ( & vid_conwidth ) ;
}
R2D_Font_Changed ( ) ;
if ( scr_disabled_for_loading )
{
extern float scr_disabled_time ;
if ( Sys_DoubleTime ( ) - scr_disabled_time > 60 | | Key_Dest_Has ( ~ kdm_game ) )
{
scr_disabled_for_loading = false ;
}
else
{
// IDirect3DDevice9_BeginScene(pD3DDev9);
scr_drawloading = true ;
SCR_DrawLoading ( true ) ;
scr_drawloading = false ;
2016-07-26 11:47:59 +00:00
if ( R2D_Flush )
R2D_Flush ( ) ;
2016-07-12 00:40:13 +00:00
// IDirect3DDevice9_EndScene(pD3DDev9);
D3D11_PresentOrCrash ( ) ;
return true ;
}
}
if ( ! scr_initialized | | ! con_initialized )
{
return false ; // not initialized yet
}
Shader_DoReload ( ) ;
# ifdef VM_UI
uimenu = UI_MenuState ( ) ;
# else
uimenu = 0 ;
# endif
// d3d11error(IDirect3DDevice9_BeginScene(pD3DDev9));
/*
# ifdef TEXTEDITOR
if ( editormodal )
{
Editor_Draw ( ) ;
V_UpdatePalette ( false ) ;
Media_RecordFrame ( ) ;
R2D_BrightenScreen ( ) ;
if ( key_dest = = key_console )
Con_DrawConsole ( vid_conheight . value / 2 , false ) ;
GL_EndRendering ( ) ;
GL_DoSwap ( ) ;
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
return ;
}
# endif
*/
if ( Media_ShowFilm ( ) )
{
M_Draw ( 0 ) ;
// V_UpdatePalette (false);
Media_RecordFrame ( ) ;
// R2D_BrightenScreen();
// IDirect3DDevice9_EndScene(pD3DDev9);
D3D11_PresentOrCrash ( ) ;
return true ;
}
//
// do 3D refresh drawing, and then update the screen
//
SCR_SetUpToDrawConsole ( ) ;
noworld = false ;
nohud = false ;
# ifdef VM_CG
if ( CG_Refresh ( ) )
nohud = true ;
else
# endif
# ifdef CSQC_DAT
if ( CSQC_DrawView ( ) )
nohud = true ;
else
# endif
if ( uimenu ! = 1 )
{
if ( r_worldentity . model & & cls . state = = ca_active )
2017-02-21 20:22:07 +00:00
V_RenderView ( ) ;
2016-07-12 00:40:13 +00:00
else
{
noworld = true ;
}
}
D3D11_Set2D ( ) ;
if ( ! noworld )
{
R2D_BrightenScreen ( ) ;
}
scr_con_forcedraw = false ;
if ( noworld )
{
if ( ( ! Key_Dest_Has ( ~ ( kdm_game | kdm_console ) ) ) & & SCR_GetLoadingStage ( ) = = LS_NONE )
scr_con_current = vid . height ;
if ( scr_con_current ! = vid . height )
R2D_ConsoleBackground ( 0 , vid . height , true ) ;
else
scr_con_forcedraw = true ;
nohud = true ;
}
SCR_DrawTwoDimensional ( uimenu , nohud ) ;
V_UpdatePalette ( false ) ;
Media_RecordFrame ( ) ;
RSpeedShow ( ) ;
D3D11_PresentOrCrash ( ) ;
window_center_x = ( window_rect . left + window_rect . right ) / 2 ;
window_center_y = ( window_rect . top + window_rect . bottom ) / 2 ;
INS_UpdateGrabs ( modestate ! = MS_WINDOWED , vid . activeapp ) ;
return true ;
}
static void D3D11_Draw_Init ( void )
{
R2D_Init ( ) ;
}
static void D3D11_Draw_Shutdown ( void )
{
R2D_Shutdown ( ) ;
}
static void D3D11_R_Init ( void )
{
}
static void D3D11_R_DeInit ( void )
{
R_GAliasFlushSkinCache ( true ) ;
Surf_DeInit ( ) ;
D3D11BE_Shutdown ( ) ;
Shader_Shutdown ( ) ;
}
static void D3D11_SetupViewPort ( void )
{
int x , x2 , y2 , y ;
float fov_x , fov_y ;
// D3DVIEWPORT9 vport;
AngleVectors ( r_refdef . viewangles , vpn , vright , vup ) ;
VectorCopy ( r_refdef . vieworg , r_origin ) ;
//
// set up viewpoint
//
x = r_refdef . vrect . x * vid . pixelwidth / ( int ) vid . width ;
x2 = ( r_refdef . vrect . x + r_refdef . vrect . width ) * vid . pixelwidth / ( int ) vid . width ;
y = ( r_refdef . vrect . y ) * vid . pixelheight / ( int ) vid . height ;
y2 = ( ( int ) ( r_refdef . vrect . y + r_refdef . vrect . height ) ) * vid . pixelheight / ( int ) vid . height ;
// fudge around because of frac screen scale
if ( x > 0 )
x - - ;
if ( x2 < vid . pixelwidth )
x2 + + ;
if ( y < 0 )
y - - ;
if ( y2 < vid . pixelheight )
y2 + + ;
fov_x = r_refdef . fov_x ; //+sin(cl.time)*5;
fov_y = r_refdef . fov_y ; //-sin(cl.time+1)*5;
if ( ( r_refdef . flags & RDF_UNDERWATER ) & & ! ( r_refdef . flags & RDF_WATERWARP ) )
{
fov_x * = 1 + ( ( ( sin ( cl . time * 4.7 ) + 1 ) * 0.015 ) * r_waterwarp . value ) ;
fov_y * = 1 + ( ( ( sin ( cl . time * 3.0 ) + 1 ) * 0.015 ) * r_waterwarp . value ) ;
}
/*view matrix*/
Matrix4x4_CM_ModelViewMatrixFromAxis ( r_refdef . m_view , vpn , vright , vup , r_refdef . vieworg ) ;
2016-10-22 07:06:51 +00:00
if ( r_refdef . maxdist )
Matrix4x4_CM_Projection_Far ( r_refdef . m_projection , fov_x , fov_y , r_refdef . mindist , r_refdef . maxdist ) ;
else
Matrix4x4_CM_Projection_Inf ( r_refdef . m_projection , fov_x , fov_y , r_refdef . mindist ) ;
2016-07-12 00:40:13 +00:00
}
static void ( D3D11_R_RenderView ) ( void )
{
float x , x2 , y , y2 ;
double time1 = 0 , time2 = 0 ;
qboolean dofbo = * r_refdef . rt_destcolour [ 0 ] . texname | | * r_refdef . rt_depth . texname ;
// texid_t colourrt[1];
2016-07-21 19:27:59 +00:00
if ( ! r_norefresh . value )
2016-07-12 00:40:13 +00:00
{
2016-07-21 19:27:59 +00:00
if ( r_speeds . ival )
time1 = Sys_DoubleTime ( ) ;
if ( dofbo )
D3D11_ApplyRenderTargets ( true ) ;
2016-07-12 00:40:13 +00:00
else
2016-07-21 19:27:59 +00:00
ID3D11DeviceContext_ClearDepthStencilView ( d3ddevctx , fb_backdepthstencil , D3D11_CLEAR_DEPTH , 1 , 0 ) ; //is it faster to clear the stencil too?
2016-07-12 00:40:13 +00:00
2016-07-21 19:27:59 +00:00
//check if we can do underwater warp
if ( cls . protocol ! = CP_QUAKE2 ) //quake2 tells us directly
{
if ( r_viewcontents & FTECONTENTS_FLUID )
r_refdef . flags | = RDF_UNDERWATER ;
else
r_refdef . flags & = ~ RDF_UNDERWATER ;
}
if ( r_refdef . flags & RDF_UNDERWATER )
2016-07-12 00:40:13 +00:00
{
2016-07-21 19:27:59 +00:00
extern cvar_t r_projection ;
if ( ! r_waterwarp . value | | r_projection . ival )
r_refdef . flags & = ~ RDF_UNDERWATER ; //no warp at all
// else if (r_waterwarp.value > 0 && scenepp_waterwarp)
// r_refdef.flags |= RDF_WATERWARP; //try fullscreen warp instead if we can
2016-07-12 00:40:13 +00:00
}
2016-07-21 19:27:59 +00:00
D3D11_SetupViewPort ( ) ;
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
x = ( r_refdef . vrect . x * ( int ) vid . pixelwidth ) / ( int ) vid . width ;
x2 = ( r_refdef . vrect . x + r_refdef . vrect . width ) * ( int ) vid . pixelwidth / ( int ) vid . width ;
y = ( r_refdef . vrect . y * ( int ) vid . pixelheight ) / ( int ) vid . height ;
y2 = ( r_refdef . vrect . y + r_refdef . vrect . height ) * ( int ) vid . pixelheight / ( int ) vid . height ;
r_refdef . pxrect . x = floor ( x ) ;
r_refdef . pxrect . y = floor ( y ) ;
r_refdef . pxrect . width = ( int ) ceil ( x2 ) - r_refdef . pxrect . x ;
r_refdef . pxrect . height = ( int ) ceil ( y2 ) - r_refdef . pxrect . y ;
Surf_SetupFrame ( ) ;
//fixme: waterwarp fov
R_SetFrustum ( r_refdef . m_projection , r_refdef . m_view ) ;
RQ_BeginFrame ( ) ;
// if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
// {
// if (cl.worldmodel)
// P_DrawParticles ();
// }
if ( ! ( r_refdef . flags & RDF_NOWORLDMODEL ) )
if ( ! r_worldentity . model | | r_worldentity . model - > loadstate ! = MLS_LOADED | | ! cl . worldmodel )
{
D3D11_Set2D ( ) ;
R2D_ImageColours ( 0 , 0 , 0 , 1 ) ;
R2D_FillBlock ( r_refdef . vrect . x , r_refdef . vrect . y , r_refdef . vrect . width , r_refdef . vrect . height ) ;
R2D_ImageColours ( 1 , 1 , 1 , 1 ) ;
if ( dofbo )
D3D11_ApplyRenderTargets ( false ) ;
return ;
}
Surf_DrawWorld ( ) ;
RQ_RenderBatchClear ( ) ;
2016-07-12 00:40:13 +00:00
2016-07-21 19:27:59 +00:00
if ( r_speeds . ival )
{
time2 = Sys_DoubleTime ( ) ;
RQuantAdd ( RQUANT_MSECS , ( int ) ( ( time2 - time1 ) * 1000000 ) ) ;
}
2016-07-12 00:40:13 +00:00
2016-07-21 19:27:59 +00:00
if ( dofbo )
D3D11_ApplyRenderTargets ( false ) ;
}
D3D11_Set2D ( ) ;
2016-07-12 00:40:13 +00:00
}
void D3D11BE_RenderToTextureUpdate2d ( qboolean destchanged )
{
if ( destchanged )
{
if ( * r_refdef . rt_destcolour [ 0 ] . texname )
D3D11_ApplyRenderTargets ( false ) ;
else
ID3D11DeviceContext_OMSetRenderTargets ( d3ddevctx , 1 , & fb_backbuffer , fb_backdepthstencil ) ;
D3D11_Set2D ( ) ;
}
else
{
// shaderstate.tex_sourcecol = R2D_RT_GetTexture(r_refdef.rt_sourcecolour.texname, &width, &height);
// shaderstate.tex_sourcedepth = R2D_RT_GetTexture(r_refdef.rt_depth.texname, &width, &height);
}
}
rendererinfo_t d3d11rendererinfo =
{
" Direct3D11 " ,
{
" D3D11 " ,
" Direct3d11 " ,
" DirectX11 " ,
" DX11 "
} ,
QR_DIRECT3D11 ,
D3D11_Draw_Init ,
D3D11_Draw_Shutdown ,
D3D11_UpdateFiltering ,
D3D11_LoadTextureMips ,
D3D11_DestroyTexture ,
/*
D3D11_LoadTexture ,
D3D11_LoadTexture8Pal24 ,
D3D11_LoadTexture8Pal32 ,
D3D11_LoadCompressed ,
D3D11_FindTexture ,
D3D11_AllocNewTexture ,
D3D11_Upload ,
D3D11_DestroyTexture ,
*/
D3D11_R_Init ,
D3D11_R_DeInit ,
D3D11_R_RenderView ,
D3D11_VID_Init ,
D3D11_VID_DeInit ,
D3D11_PresentOrCrash ,
D3D11_VID_ApplyGammaRamps ,
NULL ,
NULL ,
NULL ,
D3D11_VID_SetWindowCaption ,
D3D11_VID_GetRGBInfo ,
D3D11_SCR_UpdateScreen ,
D3D11BE_SelectMode ,
D3D11BE_DrawMesh_List ,
D3D11BE_DrawMesh_Single ,
D3D11BE_SubmitBatch ,
D3D11BE_GetTempBatch ,
D3D11BE_DrawWorld ,
D3D11BE_Init ,
D3D11BE_GenBrushModelVBO ,
D3D11BE_ClearVBO ,
D3D11BE_UploadAllLightmaps ,
D3D11BE_SelectEntity ,
D3D11BE_SelectDLight ,
D3D11BE_Scissor ,
D3D11BE_LightCullModel ,
D3D11BE_VBO_Begin ,
D3D11BE_VBO_Data ,
D3D11BE_VBO_Finish ,
D3D11BE_VBO_Destroy ,
D3D11BE_RenderToTextureUpdate2d ,
" no more "
} ;
# endif