2012-09-30 05:52:03 +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>
2014-03-30 08:55:06 +00:00
ID3D11Device * pD3DDev11 ;
ID3D11DeviceContext * d3ddevctx ;
# 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
2012-09-30 05:52:03 +00:00
/*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
2014-03-30 08:55:06 +00:00
# endif
2012-09-30 05:52:03 +00:00
# define DEFINE_QGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
const GUID DECLSPEC_SELECTANY name \
= { l , w1 , w2 , { b1 , b2 , b3 , b4 , b5 , b6 , b7 , b8 } }
DEFINE_QGUID ( qIID_ID3D11Texture2D , 0x6f15aaf2 , 0xd208 , 0x4e89 , 0x9a , 0xb4 , 0x48 , 0x95 , 0x35 , 0xd3 , 0x4f , 0x9c ) ;
2014-03-30 08:55:06 +00:00
# ifdef WINRT
IDXGISwapChain1 * d3dswapchain ;
# else
2012-09-30 05:52:03 +00:00
IDXGISwapChain * d3dswapchain ;
2014-03-30 08:55:06 +00:00
# endif
IDXGIOutput * d3dscreen ;
2012-09-30 05:52:03 +00:00
ID3D11RenderTargetView * fb_backbuffer ;
ID3D11DepthStencilView * fb_backdepthstencil ;
void * d3d11mod ;
qboolean vid_initializing ;
extern qboolean scr_initialized ; // ready to draw
extern qboolean scr_drawloading ;
extern qboolean scr_con_forcedraw ;
static qboolean d3d_resized ;
cvar_t vid_hardwaregamma ;
//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 ) ;
2013-11-21 23:02:28 +00:00
#if 0 //def _DEBUG
# include <dxgidebug.h>
const GUID IID_IDXGIDebug = { 0x119E7452 , 0xDE9E , 0x40fe , { 0x88 , 0x06 , 0x88 , 0xF9 , 0x0C , 0x12 , 0xB4 , 0x41 } } ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
const GUID DXGI_DEBUG_ALL = { 0xe48ae283 , 0xda80 , 0x490b , { 0x87 , 0xe6 , 0x43 , 0xe9 , 0xa9 , 0xcf , 0xda , 0x8 } } ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
void DoDXGIDebug ( void )
{
IDXGIDebug * dbg = NULL ;
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
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
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
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 ( " %x " , hr ) ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
}
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
static void D3D11_PresentOrCrash ( void )
{
2014-02-07 08:38:40 +00:00
extern cvar_t vid_vsync ;
HRESULT hr = IDXGISwapChain_Present ( d3dswapchain , vid_vsync . ival , 0 ) ;
2013-11-21 23:02:28 +00:00
if ( FAILED ( hr ) )
Sys_Error ( " IDXGISwapChain_Present: %s \n " , D3D_NameForResult ( hr ) ) ;
2012-09-30 05:52:03 +00:00
}
typedef enum { MS_WINDOWED , MS_FULLSCREEN , MS_FULLDIB , MS_UNINIT } modestate_t ;
static modestate_t modestate ;
2014-03-30 08:55:06 +00:00
# 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.
2012-09-30 05:52:03 +00:00
static void D3DVID_UpdateWindowStatus ( HWND hWnd )
{
POINT p ;
RECT nr ;
int window_width , window_height ;
GetClientRect ( hWnd , & nr ) ;
2014-03-30 08:55:06 +00:00
// Sys_Printf("Update: %i %i %i %i\n", nr.left, nr.top, nr.right, nr.bottom);
2012-12-04 19:37:57 +00:00
2012-09-30 05:52:03 +00:00
//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 ;
2014-03-30 08:55:06 +00:00
// Sys_Printf("Window: %i %i %i %i\n", window_x, window_y, window_width, window_height);
2012-12-04 19:37:57 +00:00
2012-10-14 09:00:49 +00:00
INS_UpdateClipCursor ( ) ;
2012-09-30 05:52:03 +00:00
}
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 ( ActiveApp = = fActive & & Minimized = = minimize )
return false ; //so windows doesn't crash us over and over again.
ActiveApp = fActive ;
Minimized = minimize ;
// enable/disable sound on focus gain/loss
if ( ! ActiveApp & & sound_active )
{
S_BlockSound ( ) ;
sound_active = false ;
}
else if ( ActiveApp & & ! sound_active )
{
S_UnblockSound ( ) ;
sound_active = true ;
}
2012-10-14 11:20:14 +00:00
INS_UpdateGrabs ( modestate ! = MS_WINDOWED , ActiveApp ) ;
2012-09-30 05:52:03 +00:00
return true ;
}
2014-03-30 08:55:06 +00:00
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 ) ;
2012-09-30 05:52:03 +00:00
2014-03-30 08:55:06 +00:00
D3D11BE_Reset ( true ) ;
resetd3dbackbuffer ( vid . pixelwidth , vid . pixelheight ) ;
D3D11BE_Reset ( false ) ;
}
2012-09-30 05:52:03 +00:00
static LRESULT WINAPI D3D11_WindowProc ( HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam )
{
2012-12-04 19:37:57 +00:00
LONG lRet = 0 ;
2012-09-30 05:52:03 +00:00
int fActive , fMinimized , temp ;
extern unsigned int uiWheelMessage ;
2012-12-04 19:37:57 +00:00
extern qboolean keydown [ K_MAX ] ;
2012-09-30 05:52:03 +00:00
if ( uMsg = = uiWheelMessage )
uMsg = WM_MOUSEWHEEL ;
switch ( uMsg )
{
2012-12-04 19:37:57 +00:00
# if 1
2012-09-30 05:52:03 +00:00
/* 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 :
2013-04-13 08:15:18 +00:00
if ( keydown [ K_LALT ] & & wParam = = ' \r ' )
2012-12-04 19:37:57 +00:00
{
2014-03-30 08:55:06 +00:00
if ( d3dscreen )
{
IDXGIOutput_Release ( d3dscreen ) ;
d3dscreen = NULL ;
}
2012-12-04 19:37:57 +00:00
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 ;
2014-03-30 08:55:06 +00:00
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 ;
}
2012-12-04 19:37:57 +00:00
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 ;
}
2014-03-30 08:55:06 +00:00
if ( ! d3dscreen & & modestate = = MS_FULLSCREEN )
IDXGISwapChain_GetContainingOutput ( d3dswapchain , & d3dscreen ) ;
2014-08-25 07:35:41 +00:00
IDXGISwapChain_SetFullscreenState ( d3dswapchain , modestate = = MS_FULLSCREEN , ( modestate = = MS_FULLSCREEN ) ? d3dscreen : NULL ) ;
2012-12-04 19:37:57 +00:00
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 ) ;
2014-03-30 08:55:06 +00:00
//work around a windows bug by forcing all windows to be repainted.
InvalidateRect ( NULL , NULL , false ) ;
2012-12-04 19:37:57 +00:00
}
2014-03-30 08:55:06 +00:00
D3D11_DoResize ( ) ;
Cvar_ForceCallback ( & v_gamma ) ;
2012-12-04 19:37:57 +00:00
}
else if ( ! vid_initializing )
2012-10-14 09:00:49 +00:00
INS_TranslateKeyEvent ( wParam , lParam , true , 0 ) ;
2012-09-30 05:52:03 +00:00
break ;
case WM_KEYUP :
case WM_SYSKEYUP :
if ( ! vid_initializing )
2012-10-14 09:00:49 +00:00
INS_TranslateKeyEvent ( wParam , lParam , false , 0 ) ;
2012-09-30 05:52:03 +00:00
break ;
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 )
2012-10-14 11:20:14 +00:00
INS_MouseEvent ( temp ) ;
2012-09-30 05:52:03 +00:00
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 )
2012-10-14 11:20:14 +00:00
INS_RawInput_Read ( ( HANDLE ) lParam ) ;
2012-09-30 05:52:03 +00:00
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 ;
case WM_SIZE :
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 ) ;
2012-12-04 19:37:57 +00:00
lRet = DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
2012-09-30 05:52:03 +00:00
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 ) ;
}
break ;
case WM_ACTIVATE :
fActive = LOWORD ( wParam ) ;
fMinimized = ( BOOL ) HIWORD ( wParam ) ;
if ( ! D3D11AppActivate ( ! ( fActive = = WA_INACTIVE ) , fMinimized ) )
break ; //so, urm, tell me microsoft, what changed?
2013-06-23 02:17:02 +00:00
if ( modestate = = MS_FULLDIB )
2012-09-30 05:52:03 +00:00
ShowWindow ( mainwindow , SW_SHOWNORMAL ) ;
2014-04-12 03:31:59 +00:00
if ( modestate = = MS_FULLSCREEN )
2014-03-30 08:55:06 +00:00
{
2014-04-12 03:31:59 +00:00
IDXGISwapChain_SetFullscreenState ( d3dswapchain , ActiveApp , d3dscreen ) ;
2014-03-30 08:55:06 +00:00
D3D11_DoResize ( ) ;
}
Cvar_ForceCallback ( & v_gamma ) ;
2012-12-04 19:37:57 +00:00
2012-09-30 05:52:03 +00:00
// fix the leftover Alt from any Alt-Tab or the like that switched us away
// ClearAllStates ();
2012-12-04 19:37:57 +00:00
lRet = 1 ;
2012-09-30 05:52:03 +00:00
break ;
case WM_DESTROY :
{
// if (dibwindow)
// DestroyWindow (dibwindow);
}
break ;
case MM_MCINOTIFY :
lRet = CDAudio_MessageHandler ( hWnd , uMsg , wParam , lParam ) ;
break ;
2012-12-04 19:37:57 +00:00
# endif
case WM_ERASEBKGND :
return 1 ;
2012-09-30 05:52:03 +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 ;
}
2014-03-30 08:55:06 +00:00
# endif
2012-09-30 05:52:03 +00:00
# if (WINVER < 0x500) && !defined(__GNUC__)
typedef struct tagMONITORINFO
{
DWORD cbSize ;
RECT rcMonitor ;
RECT rcWork ;
DWORD dwFlags ;
} 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 = 1 ;
t2ddesc . SampleDesc . Quality = 0 ;
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 ;
}
2014-03-30 08:55:06 +00:00
# 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 = 1 + info - > multisample ;
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
2012-12-04 19:37:57 +00:00
static qboolean initD3D11Device ( HWND hWnd , rendererstate_t * info , PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN func , IDXGIAdapter * adapt )
2012-09-30 05:52:03 +00:00
{
2013-11-28 00:45:22 +00:00
int flags = 0 ; //= D3D11_CREATE_DEVICE_SINGLETHREADED;
2013-11-21 23:02:28 +00:00
D3D_DRIVER_TYPE drivertype ;
2012-09-30 05:52:03 +00:00
DXGI_SWAP_CHAIN_DESC scd ;
D3D_FEATURE_LEVEL flevel , flevels [ ] =
{
2013-11-21 23:02:28 +00:00
//D3D_FEATURE_LEVEL_11_1,
2012-09-30 05:52:03 +00:00
D3D_FEATURE_LEVEL_11_0 ,
D3D_FEATURE_LEVEL_10_1 ,
D3D_FEATURE_LEVEL_10_0 ,
2013-11-21 23:02:28 +00:00
//FIXME: need npot.
2014-03-30 08:55:06 +00:00
D3D_FEATURE_LEVEL_9_3 ,
D3D_FEATURE_LEVEL_9_2 ,
D3D_FEATURE_LEVEL_9_1
2012-09-30 05:52:03 +00:00
} ;
memset ( & scd , 0 , sizeof ( scd ) ) ;
2013-11-21 23:02:28 +00:00
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.
2012-09-30 05:52:03 +00:00
scd . BufferDesc . Width = info - > width ;
scd . BufferDesc . Height = info - > height ;
scd . BufferDesc . RefreshRate . Numerator = 0 ;
scd . BufferDesc . RefreshRate . Denominator = 0 ;
2013-11-21 23:02:28 +00:00
scd . BufferCount = 1 + info - > triplebuffer ; //back buffer count
2014-03-30 08:55:06 +00:00
scd . BufferDesc . Format = info - > srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM ; //32bit colour
2012-09-30 05:52:03 +00:00
scd . BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT ;
scd . OutputWindow = hWnd ;
2014-03-30 08:55:06 +00:00
scd . SampleDesc . Count = 1 + info - > multisample ; //as we're starting up windowed (and switching to fullscreen after), the frontbuffer is handled by windows.
2012-09-30 05:52:03 +00:00
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
2013-11-21 23:02:28 +00:00
if ( drivertype = = D3D_DRIVER_TYPE_UNKNOWN & & adapt )
2012-12-04 19:37:57 +00:00
{
DXGI_ADAPTER_DESC adesc ;
2013-11-21 23:02:28 +00:00
IDXGIAdapter_GetDesc ( adapt , & adesc ) ;
2012-12-04 19:37:57 +00:00
Con_Printf ( " D3D11 Adaptor: %S \n " , adesc . Description ) ;
}
2013-11-21 23:02:28 +00:00
else
adapt = NULL ;
2012-12-04 19:37:57 +00:00
2013-11-21 23:02:28 +00:00
if ( FAILED ( func ( adapt , drivertype , NULL , flags ,
2012-09-30 05:52:03 +00:00
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 )
{
}
vid . numpages = scd . BufferCount ;
2013-11-21 23:02:28 +00:00
if ( ! D3D11Shader_Init ( flevel ) )
{
Con_Printf ( " Unable to intialise a suitable HLSL compiler, please install the DirectX runtime. \n " ) ;
return false ;
}
2012-09-30 05:52:03 +00:00
return true ;
}
static void initD3D11 ( HWND hWnd , rendererstate_t * info )
{
static dllhandle_t * d3d11dll ;
2012-12-04 19:37:57 +00:00
static dllhandle_t * dxgi ;
2012-09-30 05:52:03 +00:00
static PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN fnc ;
2013-11-21 23:02:28 +00:00
static HRESULT ( WINAPI * pCreateDXGIFactory1 ) ( IID * riid , void * * ppFactory ) ;
static IID factiid = { 0x770aae78 , 0xf26f , 0x4dba , 0xa8 , 0x29 , 0x25 , 0x3c , 0x83 , 0xd1 , 0xb3 , 0x87 } ;
2012-12-04 19:37:57 +00:00
IDXGIFactory1 * fact = NULL ;
IDXGIAdapter * adapt = NULL ;
dllfunction_t d3d11funcs [ ] =
2012-09-30 05:52:03 +00:00
{
{ ( void * * ) & fnc , " D3D11CreateDeviceAndSwapChain " } ,
{ NULL }
} ;
2012-12-04 19:37:57 +00:00
dllfunction_t dxgifuncs [ ] =
{
{ ( void * * ) & pCreateDXGIFactory1 , " CreateDXGIFactory1 " } ,
{ NULL }
} ;
2012-09-30 05:52:03 +00:00
2012-12-04 19:37:57 +00:00
if ( ! dxgi )
dxgi = Sys_LoadLibrary ( " dxgi " , dxgifuncs ) ;
2013-11-21 23:02:28 +00:00
if ( ! d3d11mod )
d3d11mod = Sys_LoadLibrary ( " d3d11 " , d3d11funcs ) ;
2012-09-30 05:52:03 +00:00
if ( ! d3d11mod )
return ;
2012-12-04 19:37:57 +00:00
if ( pCreateDXGIFactory1 )
{
2013-11-21 23:02:28 +00:00
HRESULT hr ;
hr = pCreateDXGIFactory1 ( & factiid , & fact ) ;
if ( FAILED ( hr ) )
Con_Printf ( " CreateDXGIFactory1 failed: %s \n " , D3D_NameForResult ( hr ) ) ;
2012-12-04 19:37:57 +00:00
if ( fact )
{
2013-11-21 23:02:28 +00:00
IDXGIFactory1_EnumAdapters ( fact , 0 , & adapt ) ;
2012-12-04 19:37:57 +00:00
}
}
2012-09-30 05:52:03 +00:00
2012-12-04 19:37:57 +00:00
initD3D11Device ( hWnd , info , fnc , adapt ) ;
2013-11-21 23:02:28 +00:00
if ( adapt )
IDXGIAdapter_Release ( adapt ) ;
2012-12-04 19:37:57 +00:00
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.
2013-11-21 23:02:28 +00:00
IDXGIFactory1_MakeWindowAssociation ( fact , hWnd , DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_PRINT_SCREEN ) ;
IDXGIFactory1_Release ( fact ) ;
2012-12-04 19:37:57 +00:00
}
2012-09-30 05:52:03 +00:00
}
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 ;
extern cvar_t vid_conwidth ;
//extern cvar_t vid_conheight;
//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 = LoadCursor ( NULL , IDC_ARROW ) ;
wc . hInstance = global_hInstance ;
vid_initializing = true ;
RegisterClass ( & wc ) ;
2012-12-04 19:37:57 +00:00
modestate = info - > fullscreen ? MS_FULLSCREEN : MS_WINDOWED ;
2012-09-30 05:52:03 +00:00
2012-12-04 19:37:57 +00:00
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 ;
2012-09-30 05:52:03 +00:00
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.
2013-11-21 23:02:28 +00:00
DoDXGIDebug ( ) ;
2012-09-30 05:52:03 +00:00
initD3D11 ( mainwindow , info ) ;
if ( ! pD3DDev11 )
{
2013-11-21 23:02:28 +00:00
DoDXGIDebug ( ) ;
2012-09-30 05:52:03 +00:00
Con_Printf ( " No suitable D3D11 device found \n " ) ;
return false ;
}
if ( info - > fullscreen )
2014-03-30 08:55:06 +00:00
{
if ( ! d3dscreen )
IDXGISwapChain_GetContainingOutput ( d3dswapchain , & d3dscreen ) ;
IDXGISwapChain_SetFullscreenState ( d3dswapchain , true , d3dscreen ) ;
}
2012-09-30 05:52:03 +00:00
2013-11-21 23:02:28 +00:00
vid . pixelwidth = width ;
vid . pixelheight = height ;
2012-09-30 05:52:03 +00:00
while ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) )
{
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
CL_UpdateWindowTitle ( ) ;
ShowWindow ( mainwindow , SW_SHOWNORMAL ) ;
2013-11-21 23:02:28 +00:00
vid . width = vid . pixelwidth ;
vid . height = vid . pixelheight ;
2012-09-30 05:52:03 +00:00
vid_initializing = false ;
GetWindowRect ( mainwindow , & window_rect ) ;
{
extern qboolean mouseactive ;
mouseactive = false ;
}
return true ;
}
2014-03-30 08:55:06 +00:00
# endif
2012-09-30 05:52:03 +00:00
/*a new model has been loaded*/
static void ( D3D11_R_NewMap ) ( void )
{
r_worldentity . model = cl . worldmodel ;
# ifdef MAP_PROC
if ( cl . worldmodel & & cl . worldmodel - > fromgame = = fg_doom3 )
D3_GenerateAreas ( cl . worldmodel ) ;
# endif
/*wipe any lingering particles*/
P_ClearParticles ( ) ;
CL_RegisterParticles ( ) ;
R_AnimateLight ( ) ;
Surf_DeInit ( ) ;
Surf_WipeStains ( ) ;
Surf_BuildLightmaps ( ) ;
TP_NewMap ( ) ;
R_SetSky ( cl . skyname ) ;
# ifdef RTLIGHTS
Sh_PreGenerateLights ( ) ;
# endif
}
extern mleaf_t * r_viewleaf , * r_oldviewleaf ;
extern mleaf_t * r_viewleaf2 , * r_oldviewleaf2 ;
static void ( D3D11_R_PreNewMap ) ( void )
{
r_viewleaf = NULL ;
r_oldviewleaf = NULL ;
r_viewleaf2 = NULL ;
r_oldviewleaf2 = NULL ;
}
static void ( D3D11_VID_DeInit ) ( void )
{
D3D11BE_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 )
2013-11-21 23:02:28 +00:00
ID3D11Device_Release ( pD3DDev11 ) ;
2012-09-30 05:52:03 +00:00
pD3DDev11 = NULL ;
2013-11-21 23:02:28 +00:00
2012-09-30 05:52:03 +00:00
if ( d3ddevctx )
2013-11-21 23:02:28 +00:00
{
ID3D11DeviceContext_ClearState ( d3ddevctx ) ;
ID3D11DeviceContext_Flush ( d3ddevctx ) ;
ID3D11DeviceContext_Release ( d3ddevctx ) ;
}
2012-09-30 05:52:03 +00:00
d3ddevctx = NULL ;
2014-03-30 08:55:06 +00:00
# ifndef WINRT
2012-09-30 05:52:03 +00:00
if ( mainwindow )
{
DestroyWindow ( mainwindow ) ;
mainwindow = NULL ;
}
2014-03-30 08:55:06 +00:00
# endif
if ( d3dscreen )
IUnknown_Release ( d3dscreen ) ;
d3dscreen = NULL ;
2013-11-21 23:02:28 +00:00
DoDXGIDebug ( ) ;
2012-09-30 05:52:03 +00:00
}
2014-03-30 08:55:06 +00:00
extern float hw_blend [ 4 ] ; // rgba 0.0 - 1.0
static void D3D11_BuildRamps ( int points , DXGI_RGB * out )
{
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 ;
}
}
2013-05-11 14:02:55 +00:00
static qboolean D3D11_VID_ApplyGammaRamps ( unsigned short * ramps )
2012-09-30 05:52:03 +00:00
{
2014-03-30 08:55:06 +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 ;
}
2013-05-11 14:02:55 +00:00
return false ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
static char * D3D11_VID_GetRGBInfo ( int prepad , int * truevidwidth , int * truevidheight )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +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 ) ) )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
r = rgb = BZ_Malloc ( prepad + 3 * vid . pixelwidth * vid . pixelheight ) ;
r + = prepad ;
for ( y = vid . pixelheight ; y - - > 0 ; )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
in = lock . pData ;
in + = y * lock . RowPitch ;
for ( x = 0 ; x < vid . pixelwidth ; x + + , rgb + = 3 , in + = 4 )
2012-09-30 05:52:03 +00:00
{
2013-11-21 23:02:28 +00:00
rgb [ 0 ] = in [ 0 ] ;
rgb [ 1 ] = in [ 1 ] ;
rgb [ 2 ] = in [ 2 ] ;
2012-09-30 05:52:03 +00:00
}
}
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_Unmap ( d3ddevctx , ( ID3D11Resource * ) texture , 0 ) ;
2012-09-30 05:52:03 +00:00
}
2013-11-21 23:02:28 +00:00
ID3D11Texture2D_Release ( texture ) ;
* truevidwidth = vid . pixelwidth ;
* truevidheight = vid . pixelheight ;
return r ;
2012-09-30 05:52:03 +00:00
}
static void ( D3D11_VID_SetWindowCaption ) ( char * msg )
{
2014-03-30 08:55:06 +00:00
# ifndef WINRT
2012-09-30 05:52:03 +00:00
SetWindowText ( mainwindow , msg ) ;
2014-03-30 08:55:06 +00:00
# endif
2012-09-30 05:52:03 +00:00
}
void D3D11_Set2D ( void )
{
D3D11_VIEWPORT vport ;
2013-11-21 23:02:28 +00:00
// 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 ) ;
2012-09-30 05:52:03 +00:00
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 ;
2013-11-21 23:02:28 +00:00
ID3D11DeviceContext_RSSetViewports ( d3ddevctx , 1 , & vport ) ;
2012-09-30 05:52:03 +00:00
D3D11BE_SetupViewCBuffer ( ) ;
}
static void ( D3D11_SCR_UpdateScreen ) ( void )
{
//extern int keydown[];
//extern cvar_t vid_conheight;
int uimenu ;
# ifdef TEXTEDITOR
//extern qboolean editormodal;
# endif
qboolean nohud , noworld ;
RSpeedMark ( ) ;
if ( r_clear . ival )
{
2014-03-30 08:55:06 +00:00
float colours [ 4 ] = { ( r_clear . ival = = 2 ) ? 0 : 1 , 0 , 0 , 0 } ;
2012-09-30 05:52:03 +00:00
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 ) ;
}
2014-03-30 08:55:06 +00:00
R2D_Font_Changed ( ) ;
2012-09-30 05:52:03 +00:00
if ( scr_disabled_for_loading )
{
extern float scr_disabled_time ;
2013-10-08 16:13:18 +00:00
if ( Sys_DoubleTime ( ) - scr_disabled_time > 60 | | Key_Dest_Has ( ~ kdm_game ) )
2012-09-30 05:52:03 +00:00
{
scr_disabled_for_loading = false ;
}
else
{
// IDirect3DDevice9_BeginScene(pD3DDev9);
scr_drawloading = true ;
2014-03-30 08:55:06 +00:00
SCR_DrawLoading ( true ) ;
2012-09-30 05:52:03 +00:00
scr_drawloading = false ;
// IDirect3DDevice9_EndScene(pD3DDev9);
2013-11-21 23:02:28 +00:00
D3D11_PresentOrCrash ( ) ;
2012-09-30 05:52:03 +00:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
return ;
}
}
if ( ! scr_initialized | | ! con_initialized )
{
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
return ; // 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 ) ;
# if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame ( ) ;
# endif
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);
# if defined(_WIN32)
Media_RecordFrame ( ) ;
# endif
// R2D_BrightenScreen();
// IDirect3DDevice9_EndScene(pD3DDev9);
2013-11-21 23:02:28 +00:00
D3D11_PresentOrCrash ( ) ;
2012-09-30 05:52:03 +00:00
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
return ;
}
//
// 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
2013-08-27 13:18:09 +00:00
if ( CSQC_DrawView ( ) )
2012-09-30 05:52:03 +00:00
nohud = true ;
else
# endif
if ( uimenu ! = 1 )
{
if ( r_worldentity . model & & cls . state = = ca_active )
V_RenderView ( ) ;
else
{
noworld = true ;
}
}
D3D11_Set2D ( ) ;
if ( ! noworld )
{
R2D_PolyBlend ( ) ;
R2D_BrightenScreen ( ) ;
}
scr_con_forcedraw = false ;
if ( noworld )
{
2013-10-08 16:13:18 +00:00
if ( ( ! Key_Dest_Has ( ~ ( kdm_game | kdm_console ) ) ) & & SCR_GetLoadingStage ( ) = = LS_NONE )
2012-09-30 05:52:03 +00:00
scr_con_current = vid . height ;
if ( scr_con_current ! = vid . height )
R2D_ConsoleBackground ( 0 , vid . height , true ) ;
else
scr_con_forcedraw = true ;
nohud = true ;
}
else if ( ! nohud )
SCR_TileClear ( ) ;
SCR_DrawTwoDimensional ( uimenu , nohud ) ;
V_UpdatePalette ( false ) ;
2012-12-04 19:37:57 +00:00
2012-09-30 05:52:03 +00:00
# if defined(_WIN32) && defined(GLQUAKE)
Media_RecordFrame ( ) ;
# endif
RSpeedEnd ( RSPEED_TOTALREFRESH ) ;
RSpeedShow ( ) ;
2013-11-21 23:02:28 +00:00
D3D11_PresentOrCrash ( ) ;
2012-09-30 05:52:03 +00:00
window_center_x = ( window_rect . left + window_rect . right ) / 2 ;
window_center_y = ( window_rect . top + window_rect . bottom ) / 2 ;
2012-10-14 11:20:14 +00:00
INS_UpdateGrabs ( modestate ! = MS_WINDOWED , ActiveApp ) ;
2012-09-30 05:52:03 +00:00
}
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 )
{
2014-03-30 08:55:06 +00:00
GL_GAliasFlushSkinCache ( ) ;
2012-09-30 05:52:03 +00:00
Surf_DeInit ( ) ;
Shader_Shutdown ( ) ;
D3D11_Image_Shutdown ( ) ;
}
static void D3D11_SetupViewPort ( void )
{
extern cvar_t gl_mindist ;
float screenaspect ;
int x , x2 , y2 , y , w , h ;
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 + + ;
w = x2 - x ;
h = y2 - y ;
fov_x = r_refdef . fov_x ; //+sin(cl.time)*5;
fov_y = r_refdef . fov_y ; //-sin(cl.time+1)*5;
if ( r_waterwarp . value < 0 & & r_viewcontents & FTECONTENTS_FLUID )
{
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 ) ;
}
screenaspect = ( float ) r_refdef . vrect . width / r_refdef . vrect . height ;
/*view matrix*/
Matrix4x4_CM_ModelViewMatrixFromAxis ( r_refdef . m_view , vpn , vright , vup , r_refdef . vieworg ) ;
Matrix4x4_CM_Projection_Inf ( r_refdef . m_projection , fov_x , fov_y , gl_mindist . value ) ;
}
static void ( D3D11_R_RenderView ) ( void )
{
2013-11-21 23:02:28 +00:00
float x , x2 , y , y2 ;
2014-03-30 08:55:06 +00:00
double time1 = 0 , time2 = 0 ;
if ( r_speeds . ival )
time1 = Sys_DoubleTime ( ) ;
2013-11-21 23:02:28 +00:00
2012-09-30 05:52:03 +00:00
D3D11_SetupViewPort ( ) ;
//unlike gl, we clear colour beforehand, because that seems more sane.
//always clear depth
ID3D11DeviceContext_ClearDepthStencilView ( d3ddevctx , fb_backdepthstencil , D3D11_CLEAR_DEPTH , 1 , 0 ) ; //is it faster to clear the stencil too?
2013-11-21 23:02:28 +00:00
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 ;
2014-03-30 08:55:06 +00:00
Surf_SetupFrame ( ) ;
//fixme: waterwarp fov
2012-09-30 05:52:03 +00:00
R_SetFrustum ( r_refdef . m_projection , r_refdef . m_view ) ;
RQ_BeginFrame ( ) ;
2013-11-21 23:02:28 +00:00
// if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL))
// {
// if (cl.worldmodel)
// P_DrawParticles ();
// }
2014-03-31 17:06:41 +00:00
if ( ! ( r_refdef . flags & RDF_NOWORLDMODEL ) )
2013-11-21 23:02:28 +00:00
if ( ! r_worldentity . model | | r_worldentity . model - > needload | | ! 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 ) ;
return ;
}
2012-09-30 05:52:03 +00:00
Surf_DrawWorld ( ) ;
RQ_RenderBatchClear ( ) ;
D3D11_Set2D ( ) ;
2014-03-30 08:55:06 +00:00
if ( r_speeds . ival )
{
time2 = Sys_DoubleTime ( ) ;
RQuantAdd ( RQUANT_MSECS , ( int ) ( ( time2 - time1 ) * 1000000 ) ) ;
}
2012-09-30 05:52:03 +00:00
}
2014-02-07 14:57:07 +00:00
void D3D11BE_RenderToTextureUpdate2d ( qboolean destchanged )
{
}
2012-09-30 05:52:03 +00:00
rendererinfo_t d3d11rendererinfo =
{
" Direct3D11 " ,
{
" D3D11 " ,
" Direct3d11 " ,
" DirectX11 " ,
" DX11 "
} ,
QR_DIRECT3D11 ,
D3D11_Draw_Init ,
D3D11_Draw_Shutdown ,
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_R_NewMap ,
D3D11_R_PreNewMap ,
D3D11_VID_Init ,
D3D11_VID_DeInit ,
2014-03-30 08:55:06 +00:00
D3D11_PresentOrCrash ,
2013-05-11 14:02:55 +00:00
D3D11_VID_ApplyGammaRamps ,
2012-09-30 05:52:03 +00:00
D3D11_VID_SetWindowCaption ,
2014-03-30 08:55:06 +00:00
D3D11_VID_GetRGBInfo ,
2012-09-30 05:52:03 +00:00
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 ,
2013-06-23 02:17:02 +00:00
D3D11BE_Scissor ,
2012-09-30 05:52:03 +00:00
D3D11BE_LightCullModel ,
2013-04-06 03:36:00 +00:00
D3D11BE_VBO_Begin ,
D3D11BE_VBO_Data ,
D3D11BE_VBO_Finish ,
D3D11BE_VBO_Destroy ,
2014-02-07 14:57:07 +00:00
D3D11BE_RenderToTextureUpdate2d ,
2012-09-30 05:52:03 +00:00
" no more "
} ;
# endif