2018-11-16 00:31:39 +01:00
/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System ( TM ) emulator .
This file is licensed under the Snes9x License .
For further information , consult the LICENSE file in the root directory .
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-09-25 17:46:12 +02:00
# pragma comment( lib, "d3d9" )
# include "cdirect3d.h"
# include "win32_display.h"
2010-09-25 19:35:19 +02:00
# include "../snes9x.h"
2010-09-25 17:46:12 +02:00
# include "../gfx.h"
2010-09-25 19:35:19 +02:00
# include "../display.h"
2010-09-25 17:46:12 +02:00
# include "wsnes9x.h"
2018-08-07 01:16:41 +02:00
# include "dxerr.h"
2010-09-25 17:46:12 +02:00
# include <commctrl.h>
2016-10-07 23:00:26 +02:00
2010-09-25 17:46:12 +02:00
# include "../filter/hq2x.h"
# include "../filter/2xsai.h"
# ifndef max
# define max(a, b) (((a) > (b)) ? (a) : (b))
# endif
# ifndef min
# define min(a, b) (((a) < (b)) ? (a) : (b))
# endif
2011-12-10 15:21:37 +01:00
const D3DVERTEXELEMENT9 CDirect3D : : vertexElems [ 4 ] = {
{ 0 , 0 , D3DDECLTYPE_FLOAT3 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_POSITION , 0 } ,
{ 0 , 12 , D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_TEXCOORD , 0 } ,
{ 0 , 20 , D3DDECLTYPE_FLOAT2 , D3DDECLMETHOD_DEFAULT , D3DDECLUSAGE_TEXCOORD , 1 } ,
D3DDECL_END ( )
} ;
2010-09-25 17:46:12 +02:00
/* CDirect3D::CDirect3D()
sets default values for the variables
*/
CDirect3D : : CDirect3D ( )
{
init_done = false ;
pD3D = NULL ;
pDevice = NULL ;
drawSurface = NULL ;
vertexBuffer = NULL ;
afterRenderWidth = 0 ;
afterRenderHeight = 0 ;
quadTextureSize = 0 ;
fullscreen = false ;
2010-09-25 19:35:19 +02:00
filterScale = 1 ;
for ( int i = 0 ; i < MAX_SHADER_TEXTURES ; i + + ) {
rubyLUT [ i ] = NULL ;
}
2011-02-24 01:26:42 +01:00
shader_type = D3D_SHADER_NONE ;
2010-09-25 19:35:19 +02:00
shaderTimer = 1.0f ;
shaderTimeStart = 0 ;
shaderTimeElapsed = 0 ;
2011-05-11 21:39:06 +02:00
frameCount = 0 ;
2011-02-24 01:26:42 +01:00
cgContext = NULL ;
2011-03-20 23:21:12 +01:00
cgAvailable = false ;
2011-12-10 15:21:37 +01:00
cgShader = NULL ;
vertexDeclaration = NULL ;
2010-09-25 17:46:12 +02:00
}
/* CDirect3D::~CDirect3D()
releases allocated objects
*/
CDirect3D : : ~ CDirect3D ( )
{
DeInitialize ( ) ;
}
/* CDirect3D::Initialize
Initializes Direct3D ( always in window mode )
IN :
hWnd - the HWND of the window in which we render / the focus window for fullscreen
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : Initialize ( HWND hWnd )
{
if ( init_done )
return true ;
pD3D = Direct3DCreate9 ( D3D_SDK_VERSION ) ;
if ( pD3D = = NULL ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating initial D3D9 object " ) , 0 ) ;
2010-09-25 17:46:12 +02:00
return false ;
}
2012-01-23 18:12:47 +01:00
memset ( & dPresentParams , 0 , sizeof ( dPresentParams ) ) ;
2010-09-25 17:46:12 +02:00
dPresentParams . hDeviceWindow = hWnd ;
2010-09-25 19:35:19 +02:00
dPresentParams . Windowed = true ;
2010-09-25 17:46:12 +02:00
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . SwapEffect = D3DSWAPEFFECT_DISCARD ;
dPresentParams . BackBufferFormat = D3DFMT_UNKNOWN ;
HRESULT hr = pD3D - > CreateDevice ( D3DADAPTER_DEFAULT ,
D3DDEVTYPE_HAL ,
hWnd ,
D3DCREATE_MIXED_VERTEXPROCESSING ,
& dPresentParams ,
& pDevice ) ;
if ( FAILED ( hr ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating D3D9 device " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return false ;
}
2011-12-10 15:21:37 +01:00
hr = pDevice - > CreateVertexBuffer ( sizeof ( vertexStream ) , D3DUSAGE_WRITEONLY , 0 , D3DPOOL_MANAGED , & vertexBuffer , NULL ) ;
2010-09-25 17:46:12 +02:00
if ( FAILED ( hr ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating vertex buffer " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return false ;
}
2011-12-10 15:21:37 +01:00
hr = pDevice - > CreateVertexDeclaration ( vertexElems , & vertexDeclaration ) ;
if ( FAILED ( hr ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error creating vertex declaration " ) , hr ) ;
2011-12-10 15:21:37 +01:00
return false ;
}
2011-03-20 23:21:12 +01:00
cgAvailable = loadCgFunctions ( ) ;
if ( cgAvailable ) {
cgContext = cgCreateContext ( ) ;
hr = cgD3D9SetDevice ( pDevice ) ;
if ( FAILED ( hr ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error setting cg device " ) , hr ) ;
2011-03-20 23:21:12 +01:00
}
2011-12-10 15:21:37 +01:00
cgShader = new CD3DCG ( cgContext , pDevice ) ;
2011-02-24 01:26:42 +01:00
}
2011-03-06 00:48:54 +01:00
pDevice - > SetRenderState ( D3DRS_LIGHTING , FALSE ) ;
2011-12-10 15:21:37 +01:00
pDevice - > SetRenderState ( D3DRS_ZENABLE , FALSE ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_ADDRESSU , D3DTADDRESS_BORDER ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_ADDRESSV , D3DTADDRESS_BORDER ) ;
2011-03-06 00:48:54 +01:00
2019-05-20 21:13:32 +02:00
Clear ( ) ;
2010-09-25 17:46:12 +02:00
init_done = true ;
2010-09-25 19:35:19 +02:00
ApplyDisplayChanges ( ) ;
2010-09-25 17:46:12 +02:00
return true ;
}
void CDirect3D : : DeInitialize ( )
{
DestroyDrawSurface ( ) ;
2010-09-25 19:35:19 +02:00
SetShader ( NULL ) ;
2010-09-25 17:46:12 +02:00
2011-12-10 15:21:37 +01:00
if ( cgShader ) {
delete cgShader ;
cgShader = NULL ;
}
2011-04-10 16:06:24 +02:00
if ( cgContext ) {
cgDestroyContext ( cgContext ) ;
cgContext = NULL ;
}
if ( cgAvailable )
cgD3D9SetDevice ( NULL ) ;
2010-09-25 17:46:12 +02:00
if ( vertexBuffer ) {
vertexBuffer - > Release ( ) ;
vertexBuffer = NULL ;
}
2011-12-10 15:21:37 +01:00
if ( vertexDeclaration ) {
vertexDeclaration - > Release ( ) ;
vertexDeclaration = NULL ;
}
2010-09-25 17:46:12 +02:00
if ( pDevice ) {
pDevice - > Release ( ) ;
pDevice = NULL ;
}
if ( pD3D ) {
pD3D - > Release ( ) ;
pD3D = NULL ;
}
init_done = false ;
afterRenderWidth = 0 ;
afterRenderHeight = 0 ;
quadTextureSize = 0 ;
fullscreen = false ;
2010-09-25 19:35:19 +02:00
filterScale = 0 ;
2011-04-10 16:06:24 +02:00
if ( cgAvailable )
unloadCgLibrary ( ) ;
2011-03-20 23:21:12 +01:00
cgAvailable = false ;
2010-09-25 19:35:19 +02:00
}
bool CDirect3D : : SetShader ( const TCHAR * file )
2011-02-24 01:26:42 +01:00
{
SetShaderCG ( NULL ) ;
shader_type = D3D_SHADER_NONE ;
2011-12-10 15:21:37 +01:00
if ( file ! = NULL & &
( lstrlen ( file ) > 3 & & _tcsncicmp ( & file [ lstrlen ( file ) - 3 ] , TEXT ( " .cg " ) , 3 ) = = 0 ) | |
( lstrlen ( file ) > 4 & & _tcsncicmp ( & file [ lstrlen ( file ) - 4 ] , TEXT ( " .cgp " ) , 4 ) = = 0 ) ) {
2011-02-24 01:26:42 +01:00
return SetShaderCG ( file ) ;
}
2018-08-07 01:16:41 +02:00
return true ;
2011-02-24 01:26:42 +01:00
}
2011-03-04 02:11:36 +01:00
void CDirect3D : : checkForCgError ( const char * situation )
{
char buffer [ 4096 ] ;
CGerror error = cgGetError ( ) ;
const char * string = cgGetErrorString ( error ) ;
if ( error ! = CG_NO_ERROR ) {
sprintf ( buffer ,
" Situation: %s \n "
" Error: %s \n \n "
" Cg compiler output... \n " , situation , string ) ;
MessageBoxA ( 0 , buffer ,
" Cg error " , MB_OK | MB_ICONEXCLAMATION ) ;
if ( error = = CG_COMPILER_ERROR ) {
MessageBoxA ( 0 , cgGetLastListing ( cgContext ) ,
" Cg compilation error " , MB_OK | MB_ICONEXCLAMATION ) ;
}
}
}
2011-02-24 01:26:42 +01:00
bool CDirect3D : : SetShaderCG ( const TCHAR * file )
{
2011-03-20 23:21:12 +01:00
if ( ! cgAvailable ) {
2011-12-10 15:21:37 +01:00
if ( file )
MessageBox ( NULL , TEXT ( " The CG runtime is unavailable, CG shaders will not run. \n Consult the snes9x readme for information on how to obtain the runtime. " ) , TEXT ( " CG Error " ) ,
MB_OK | MB_ICONEXCLAMATION ) ;
2011-03-20 23:21:12 +01:00
return false ;
}
2011-12-10 15:21:37 +01:00
if ( ! cgShader - > LoadShader ( file ) )
2011-02-24 01:26:42 +01:00
return false ;
shader_type = D3D_SHADER_CG ;
return true ;
}
2010-09-25 17:46:12 +02:00
/* CDirect3D::Render
does the actual rendering , changes the draw surface if necessary and recalculates
the vertex information if filter output size changes
IN :
Src - the input surface
*/
void CDirect3D : : Render ( SSurface Src )
{
SSurface Dst ;
RECT dstRect ;
2010-09-25 19:35:19 +02:00
unsigned int newFilterScale ;
2010-09-25 17:46:12 +02:00
D3DLOCKED_RECT lr ;
D3DLOCKED_RECT lrConv ;
HRESULT hr ;
if ( ! init_done ) return ;
//create a new draw surface if the filter scale changes
//at least factor 2 so we can display unscaled hi-res images
2010-09-25 19:35:19 +02:00
newFilterScale = max ( 2 , max ( GetFilterScale ( GUI . ScaleHiRes ) , GetFilterScale ( GUI . Scale ) ) ) ;
if ( newFilterScale ! = filterScale ) {
ChangeDrawSurfaceSize ( newFilterScale ) ;
2010-09-25 17:46:12 +02:00
}
if ( FAILED ( hr = pDevice - > TestCooperativeLevel ( ) ) ) {
switch ( hr ) {
case D3DERR_DEVICELOST : //do no rendering until device is restored
return ;
case D3DERR_DEVICENOTRESET : //we can reset now
2017-06-04 22:17:58 +02:00
if ( ! IsIconic ( dPresentParams . hDeviceWindow ) )
ResetDevice ( ) ;
2010-09-25 17:46:12 +02:00
return ;
default :
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Internal driver error " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return ;
}
}
//BlankTexture(drawSurface);
if ( FAILED ( hr = drawSurface - > LockRect ( 0 , & lr , NULL , 0 ) ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Unable to lock texture " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return ;
} else {
Dst . Surface = ( unsigned char * ) lr . pBits ;
Dst . Height = quadTextureSize ;
Dst . Width = quadTextureSize ;
Dst . Pitch = lr . Pitch ;
RenderMethod ( Src , Dst , & dstRect ) ;
drawSurface - > UnlockRect ( 0 ) ;
}
2019-05-20 21:13:32 +02:00
if ( ! GUI . Stretch | | GUI . AspectRatio ) {
Clear ( ) ;
}
2011-04-30 01:26:42 +02:00
2011-03-06 00:48:54 +01:00
//if the output size of the render method changes we need to update the viewport
2010-09-25 17:46:12 +02:00
if ( afterRenderHeight ! = dstRect . bottom | | afterRenderWidth ! = dstRect . right ) {
afterRenderHeight = dstRect . bottom ;
afterRenderWidth = dstRect . right ;
2011-03-06 00:48:54 +01:00
SetViewport ( ) ;
2010-09-25 17:46:12 +02:00
}
pDevice - > SetTexture ( 0 , drawSurface ) ;
2011-12-10 15:21:37 +01:00
pDevice - > SetVertexDeclaration ( vertexDeclaration ) ;
2010-09-25 17:46:12 +02:00
pDevice - > SetStreamSource ( 0 , vertexBuffer , 0 , sizeof ( VERTEX ) ) ;
2010-09-25 19:35:19 +02:00
2018-08-07 01:16:41 +02:00
if ( shader_type = = D3D_SHADER_CG ) {
RECT displayRect ;
//Get maximum rect respecting AR setting
displayRect = CalculateDisplayRect ( dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ,
dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ) ;
cgShader - > Render ( drawSurface ,
2023-03-01 00:11:55 +01:00
float2 { ( float ) quadTextureSize , ( float ) quadTextureSize } ,
float2 { ( float ) afterRenderWidth , ( float ) afterRenderHeight } ,
float2 { ( float ) ( displayRect . right - displayRect . left ) , ( float ) ( displayRect . bottom - displayRect . top ) } ,
float2 { ( float ) dPresentParams . BackBufferWidth , ( float ) dPresentParams . BackBufferHeight } ) ;
2018-08-07 01:16:41 +02:00
}
2011-12-10 15:21:37 +01:00
2018-08-07 01:16:41 +02:00
SetFiltering ( ) ;
2011-12-10 15:21:37 +01:00
2018-08-07 01:16:41 +02:00
pDevice - > SetVertexDeclaration ( vertexDeclaration ) ;
2011-12-10 15:21:37 +01:00
2018-08-07 01:16:41 +02:00
pDevice - > BeginScene ( ) ;
pDevice - > DrawPrimitive ( D3DPT_TRIANGLESTRIP , 0 , 2 ) ;
pDevice - > EndScene ( ) ;
2010-09-25 17:46:12 +02:00
2023-02-24 00:20:35 +01:00
WinThrottleFramerate ( ) ;
2010-09-25 17:46:12 +02:00
pDevice - > Present ( NULL , NULL , NULL , NULL ) ;
2018-05-05 23:31:54 +02:00
if ( GUI . ReduceInputLag )
{
IDirect3DSurface9 * surface ;
2018-05-06 18:05:09 +02:00
RECT r = { 0 , 0 , 2 , 2 } ;
2018-05-05 23:31:54 +02:00
if ( pDevice - > GetBackBuffer ( 0 , 0 , D3DBACKBUFFER_TYPE_MONO , & surface ) = = D3D_OK )
{
2018-05-06 18:05:09 +02:00
if ( surface - > LockRect ( & lr , & r , D3DLOCK_READONLY ) = = D3D_OK )
2018-05-05 23:31:54 +02:00
{
surface - > UnlockRect ( ) ;
}
surface - > Release ( ) ;
}
}
2010-09-25 17:46:12 +02:00
return ;
}
/* CDirect3D::CreateDrawSurface
calculates the necessary texture size ( multiples of 2 )
and creates a new texture
*/
void CDirect3D : : CreateDrawSurface ( )
{
2010-09-25 19:35:19 +02:00
unsigned int neededSize ;
2010-09-25 17:46:12 +02:00
HRESULT hr ;
//we need at least 512 pixels (SNES_WIDTH * 2) so we can start with that value
quadTextureSize = 512 ;
2010-09-25 19:35:19 +02:00
neededSize = SNES_WIDTH * filterScale ;
2010-09-25 17:46:12 +02:00
while ( quadTextureSize < neededSize )
quadTextureSize * = 2 ;
if ( ! drawSurface ) {
hr = pDevice - > CreateTexture (
quadTextureSize , quadTextureSize ,
1 , // 1 level, no mipmaps
0 , // dynamic textures can be locked
D3DFMT_R5G6B5 ,
D3DPOOL_MANAGED ,
& drawSurface ,
NULL ) ;
if ( FAILED ( hr ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Error while creating texture " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return ;
}
}
}
/* CDirect3D::DestroyDrawSurface
releases the old textures ( if allocated )
*/
void CDirect3D : : DestroyDrawSurface ( )
{
if ( drawSurface ) {
drawSurface - > Release ( ) ;
drawSurface = NULL ;
}
}
/* CDirect3D::BlankTexture
clears a texture ( fills it with zeroes )
IN :
texture - the texture to be blanked
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : BlankTexture ( LPDIRECT3DTEXTURE9 texture )
{
D3DLOCKED_RECT lr ;
HRESULT hr ;
if ( FAILED ( hr = texture - > LockRect ( 0 , & lr , NULL , 0 ) ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR_MSGBOX ( TEXT ( " Unable to lock texture " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return false ;
} else {
memset ( lr . pBits , 0 , lr . Pitch * quadTextureSize ) ;
texture - > UnlockRect ( 0 ) ;
return true ;
}
}
/* CDirect3D::ChangeDrawSurfaceSize
changes the draw surface size : deletes the old textures , creates a new texture
and calculate new vertices
IN :
2010-09-25 19:35:19 +02:00
scale - the scale that has to fit into the textures
2010-09-25 17:46:12 +02:00
- - - - -
returns true if successful , false otherwise
*/
2010-09-25 19:35:19 +02:00
bool CDirect3D : : ChangeDrawSurfaceSize ( unsigned int scale )
2010-09-25 17:46:12 +02:00
{
2010-09-25 19:35:19 +02:00
filterScale = scale ;
2010-09-25 17:46:12 +02:00
if ( pDevice ) {
DestroyDrawSurface ( ) ;
CreateDrawSurface ( ) ;
SetupVertices ( ) ;
return true ;
}
return false ;
}
/* CDirect3D::SetupVertices
calculates the vertex coordinates
( respecting the stretch and aspect ratio settings )
*/
void CDirect3D : : SetupVertices ( )
{
void * pLockedVertexBuffer ;
float tX = ( float ) afterRenderWidth / ( float ) quadTextureSize ;
float tY = ( float ) afterRenderHeight / ( float ) quadTextureSize ;
2011-12-10 15:21:37 +01:00
vertexStream [ 0 ] = VERTEX ( 0.0f , 0.0f , 0.0f , 0.0f , tY , 0.0f , 0.0f ) ;
vertexStream [ 1 ] = VERTEX ( 0.0f , 1.0f , 0.0f , 0.0f , 0.0f , 0.0f , 0.0f ) ;
vertexStream [ 2 ] = VERTEX ( 1.0f , 0.0f , 0.0f , tX , tY , 0.0f , 0.0f ) ;
vertexStream [ 3 ] = VERTEX ( 1.0f , 1.0f , 0.0f , tX , 0.0f , 0.0f , 0.0f ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
vertexStream [ i ] . x - = 0.5f / ( float ) dPresentParams . BackBufferWidth ;
vertexStream [ i ] . y + = 0.5f / ( float ) dPresentParams . BackBufferHeight ;
}
2010-09-25 17:46:12 +02:00
HRESULT hr = vertexBuffer - > Lock ( 0 , 0 , & pLockedVertexBuffer , NULL ) ;
2011-12-10 15:21:37 +01:00
memcpy ( pLockedVertexBuffer , vertexStream , sizeof ( vertexStream ) ) ;
2010-09-25 17:46:12 +02:00
vertexBuffer - > Unlock ( ) ;
}
2011-03-06 00:48:54 +01:00
void CDirect3D : : SetViewport ( )
{
2023-03-01 00:11:55 +01:00
D3DMATRIX matIdentity ;
D3DMATRIX matProjection ;
matIdentity = { 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
0.0f , 0.0f , 1.0f , 0.0f ,
0.0f , 0.0f , 0.0f , 1.0f } ;
matProjection = { 2.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 2.0f , 0.0f , 0.0f ,
0.0f , 0.0f , - 1.0f , 0.0f ,
- 1.0f , - 1.0f , 0.0f , 1.0f } ;
2011-03-06 00:48:54 +01:00
2018-08-07 01:16:41 +02:00
pDevice - > SetTransform ( D3DTS_WORLD , ( D3DMATRIX * ) & matIdentity ) ;
pDevice - > SetTransform ( D3DTS_VIEW , ( D3DMATRIX * ) & matIdentity ) ;
pDevice - > SetTransform ( D3DTS_PROJECTION , ( D3DMATRIX * ) & matProjection ) ;
2011-05-13 09:46:43 +02:00
2011-03-06 00:48:54 +01:00
RECT drawRect = CalculateDisplayRect ( afterRenderWidth , afterRenderHeight , dPresentParams . BackBufferWidth , dPresentParams . BackBufferHeight ) ;
D3DVIEWPORT9 viewport ;
viewport . X = drawRect . left ;
viewport . Y = drawRect . top ;
viewport . Height = drawRect . bottom - drawRect . top ;
viewport . Width = drawRect . right - drawRect . left ;
viewport . MinZ = 0.0f ;
viewport . MaxZ = 1.0f ;
HRESULT hr = pDevice - > SetViewport ( & viewport ) ;
SetupVertices ( ) ;
}
2010-09-25 17:46:12 +02:00
/* CDirect3D::ChangeRenderSize
determines if we need to reset the device ( if the size changed )
called with ( 0 , 0 ) whenever we want new settings to take effect
IN :
newWidth , newHeight - the new window size
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ChangeRenderSize ( unsigned int newWidth , unsigned int newHeight )
{
if ( ! init_done )
return false ;
//if we already have the desired size no change is necessary
//during fullscreen no changes are allowed
2010-09-25 19:35:19 +02:00
if ( dPresentParams . BackBufferWidth = = newWidth & & dPresentParams . BackBufferHeight = = newHeight )
2010-09-25 17:46:12 +02:00
return true ;
if ( ! ResetDevice ( ) )
return false ;
2011-03-06 00:48:54 +01:00
2010-09-25 17:46:12 +02:00
return true ;
}
/* CDirect3D::ResetDevice
resets the device
called if surface was lost or the settings / display size require a device reset
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ResetDevice ( )
{
2010-09-25 19:35:19 +02:00
if ( ! init_done ) return false ;
2010-09-25 17:46:12 +02:00
HRESULT hr ;
//release prior to reset
DestroyDrawSurface ( ) ;
2011-04-10 16:06:24 +02:00
if ( cgAvailable ) {
2011-12-10 15:21:37 +01:00
cgShader - > OnLostDevice ( ) ;
2011-04-10 16:06:24 +02:00
cgD3D9SetDevice ( NULL ) ;
}
2010-09-25 17:46:12 +02:00
//zero or unknown values result in the current window size/display settings
dPresentParams . BackBufferWidth = 0 ;
dPresentParams . BackBufferHeight = 0 ;
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . BackBufferFormat = D3DFMT_UNKNOWN ;
dPresentParams . FullScreen_RefreshRateInHz = 0 ;
dPresentParams . Windowed = true ;
dPresentParams . PresentationInterval = GUI . Vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE ;
2018-05-05 23:31:54 +02:00
dPresentParams . Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ;
2010-09-25 17:46:12 +02:00
if ( fullscreen ) {
dPresentParams . BackBufferWidth = GUI . FullscreenMode . width ;
dPresentParams . BackBufferHeight = GUI . FullscreenMode . height ;
dPresentParams . BackBufferCount = GUI . DoubleBuffered ? 2 : 1 ;
dPresentParams . Windowed = false ;
if ( GUI . FullscreenMode . depth = = 32 )
dPresentParams . BackBufferFormat = D3DFMT_X8R8G8B8 ;
else
dPresentParams . BackBufferFormat = D3DFMT_R5G6B5 ;
dPresentParams . FullScreen_RefreshRateInHz = GUI . FullscreenMode . rate ;
}
if ( FAILED ( hr = pDevice - > Reset ( & dPresentParams ) ) ) {
2017-02-18 05:52:11 +01:00
DXTRACE_ERR ( TEXT ( " Unable to reset device " ) , hr ) ;
2010-09-25 17:46:12 +02:00
return false ;
}
2011-04-10 16:06:24 +02:00
if ( cgAvailable ) {
cgD3D9SetDevice ( pDevice ) ;
2011-12-10 15:21:37 +01:00
cgShader - > OnResetDevice ( ) ;
2010-09-25 17:46:12 +02:00
}
2011-03-06 00:48:54 +01:00
pDevice - > SetRenderState ( D3DRS_LIGHTING , FALSE ) ;
2010-09-25 17:46:12 +02:00
pDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 1.0f , 0 ) ;
2023-02-24 00:20:35 +01:00
2010-09-25 17:46:12 +02:00
//recreate the surface
CreateDrawSurface ( ) ;
2011-04-30 01:26:42 +02:00
SetViewport ( ) ;
2010-09-25 17:46:12 +02:00
return true ;
}
/* CDirect3D::SetSnes9xColorFormat
sets the color format to 16 bit ( since the texture is always 16 bit )
no depth conversion is necessary ( done by D3D )
*/
void CDirect3D : : SetSnes9xColorFormat ( )
{
GUI . ScreenDepth = 16 ;
GUI . BlueShift = 0 ;
GUI . GreenShift = 6 ;
GUI . RedShift = 11 ;
S9xBlit2xSaIFilterInit ( ) ;
S9xBlitHQ2xFilterInit ( ) ;
GUI . NeedDepthConvert = FALSE ;
GUI . DepthConverted = TRUE ;
return ;
}
/* CDirect3D::SetFullscreen
enables / disables fullscreen mode
IN :
fullscreen - determines if fullscreen is enabled / disabled
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : SetFullscreen ( bool fullscreen )
{
if ( ! init_done )
return false ;
if ( this - > fullscreen = = fullscreen )
return true ;
this - > fullscreen = fullscreen ;
if ( ! ResetDevice ( ) )
return false ;
//present here to get a fullscreen blank even if no rendering is done
pDevice - > Present ( NULL , NULL , NULL , NULL ) ;
2011-04-30 01:26:42 +02:00
2010-09-25 17:46:12 +02:00
return true ;
}
/* CDirect3D::EnumModes
enumerates possible display modes ( only 16 and 32 bit ) and fills the vector
IN :
modeVector - pointer to the mode vector
*/
void CDirect3D : : EnumModes ( std : : vector < dMode > * modeVector )
{
D3DDISPLAYMODE d3dMode ;
int modeCount , index ;
dMode mode ;
if ( ! init_done )
return ;
//enumerate 32bit modes
modeCount = pD3D - > GetAdapterModeCount ( D3DADAPTER_DEFAULT , D3DFMT_X8R8G8B8 ) ;
for ( int i = 0 ; i < modeCount ; i + + ) {
if ( pD3D - > EnumAdapterModes ( D3DADAPTER_DEFAULT , D3DFMT_X8R8G8B8 , i , & d3dMode ) = = D3D_OK ) {
mode . width = d3dMode . Width ;
mode . height = d3dMode . Height ;
mode . rate = d3dMode . RefreshRate ;
mode . depth = 32 ;
modeVector - > push_back ( mode ) ;
}
}
//enumerate 16bit modes
modeCount = pD3D - > GetAdapterModeCount ( D3DADAPTER_DEFAULT , D3DFMT_R5G6B5 ) ;
for ( int i = 0 ; i < modeCount ; i + + ) {
if ( pD3D - > EnumAdapterModes ( D3DADAPTER_DEFAULT , D3DFMT_R5G6B5 , i , & d3dMode ) = = D3D_OK ) {
mode . width = d3dMode . Width ;
mode . height = d3dMode . Height ;
mode . rate = d3dMode . RefreshRate ;
mode . depth = 16 ;
modeVector - > push_back ( mode ) ;
}
}
}
/* CDirect3D::ApplyDisplayChanges
calls changerendersize to apply new display settings
- - - - -
returns true if successful , false otherwise
*/
bool CDirect3D : : ApplyDisplayChanges ( void )
{
2011-02-24 01:26:42 +01:00
if ( GUI . shaderEnabled & & GUI . D3DshaderFileName )
SetShader ( GUI . D3DshaderFileName ) ;
2010-09-25 19:35:19 +02:00
else
SetShader ( NULL ) ;
2010-09-25 17:46:12 +02:00
return ChangeRenderSize ( 0 , 0 ) ;
}
2011-12-10 15:21:37 +01:00
void CDirect3D : : SetFiltering ( )
{
2018-05-20 18:01:03 +02:00
if ( Settings . BilinearFilter ) {
2011-12-10 15:21:37 +01:00
pDevice - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR ) ;
} else {
pDevice - > SetSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_POINT ) ;
pDevice - > SetSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_POINT ) ;
}
}
2019-05-20 21:13:32 +02:00
// reset viewport to whole window, clear, set back to current viewport
void CDirect3D : : Clear ( )
{
if ( ! init_done )
return ;
D3DVIEWPORT9 vp_current , vp_all ;
pDevice - > GetViewport ( & vp_current ) ;
vp_all . X = 0 ;
vp_all . Y = 0 ;
vp_all . Width = dPresentParams . BackBufferWidth ;
vp_all . Height = dPresentParams . BackBufferHeight ;
vp_all . MinZ = 0.0 ;
vp_all . MaxZ = 1.0 ;
pDevice - > SetViewport ( & vp_all ) ;
pDevice - > Clear ( 0 , NULL , D3DCLEAR_TARGET , D3DCOLOR_XRGB ( 0 , 0 , 0 ) , 1.0f , 0 ) ;
pDevice - > SetViewport ( & vp_current ) ;
}