2009-07-28 21:32:10 +00:00
// Copyright (C) 2003 Dolphin Project.
2008-12-08 05:25:12 +00:00
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
2009-02-28 22:10:38 +00:00
# include <list>
2008-12-08 05:25:12 +00:00
# include <d3dx9.h>
2009-11-28 05:59:46 +00:00
# include <strsafe.h>
2008-12-08 05:25:12 +00:00
2010-01-29 07:44:21 +00:00
# include "StringUtil.h"
2008-12-08 05:25:12 +00:00
# include "Common.h"
2010-03-14 18:57:50 +00:00
# include "Atomic.h"
2010-02-02 21:56:29 +00:00
# include "FileUtil.h"
2010-01-27 22:07:59 +00:00
# include "Thread.h"
2010-01-21 21:27:52 +00:00
# include "Timer.h"
2008-12-08 05:25:12 +00:00
# include "Statistics.h"
2009-09-13 09:23:30 +00:00
# include "VideoConfig.h"
2008-12-08 05:25:12 +00:00
# include "main.h"
# include "VertexManager.h"
# include "Render.h"
# include "OpcodeDecoding.h"
2009-06-22 09:31:30 +00:00
# include "BPStructs.h"
2008-12-08 05:25:12 +00:00
# include "XFStructs.h"
# include "D3DUtil.h"
2008-12-25 15:56:36 +00:00
# include "VertexShaderManager.h"
# include "PixelShaderManager.h"
2009-02-28 22:10:38 +00:00
# include "VertexShaderCache.h"
2008-12-26 19:39:12 +00:00
# include "PixelShaderCache.h"
2009-09-13 17:46:33 +00:00
# include "VertexLoaderManager.h"
2008-12-08 05:25:12 +00:00
# include "TextureCache.h"
# include "EmuWindow.h"
2009-03-28 21:07:16 +00:00
# include "AVIDump.h"
2009-09-03 20:37:35 +00:00
# include "OnScreenDisplay.h"
2009-09-13 17:46:33 +00:00
# include "FramebufferManager.h"
2009-09-04 06:09:21 +00:00
# include "Fifo.h"
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
# include "TextureConverter.h"
2010-08-29 23:08:56 +00:00
# include "DLCache.h"
2008-12-08 05:25:12 +00:00
2009-09-02 06:33:41 +00:00
# include "debugger/debugger.h"
2010-09-28 02:15:02 +00:00
static int s_fps = 0 ;
2010-02-20 04:18:19 +00:00
2010-03-14 18:57:50 +00:00
static bool WindowResized ;
2009-09-13 17:46:33 +00:00
static int s_target_width ;
static int s_target_height ;
2009-09-13 08:21:35 +00:00
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
static int s_Fulltarget_width ;
static int s_Fulltarget_height ;
2009-09-13 08:21:35 +00:00
static int s_backbuffer_width ;
static int s_backbuffer_height ;
2010-03-14 18:57:50 +00:00
static int s_XFB_width ;
static int s_XFB_height ;
2009-09-03 20:37:35 +00:00
static float xScale ;
static float yScale ;
2008-12-08 05:25:12 +00:00
2010-06-09 15:33:01 +00:00
static float EFBxScale ;
static float EFByScale ;
2010-05-19 03:15:36 +00:00
2009-09-13 08:21:35 +00:00
static int s_recordWidth ;
static int s_recordHeight ;
2009-03-28 21:07:16 +00:00
2010-09-28 02:15:02 +00:00
static bool s_bLastFrameDumped ;
static bool s_bAVIDumping ;
2009-03-28 21:07:16 +00:00
2009-10-10 23:36:18 +00:00
static u32 s_blendMode ;
2010-02-03 22:19:00 +00:00
static u32 s_LastAA ;
2010-06-09 15:33:01 +00:00
static u32 s_LastEFBScale ;
2010-02-04 22:25:09 +00:00
static bool IS_AMD ;
2010-09-28 02:15:02 +00:00
static bool XFBWrited = false ;
2009-10-10 23:36:18 +00:00
2010-06-20 22:23:34 +00:00
// used extern by other files. need to clean this up at some point.
int frameCount ;
static char * st ;
2008-12-08 05:25:12 +00:00
2010-01-27 22:07:59 +00:00
static bool s_bScreenshot = false ;
static Common : : CriticalSection s_criticalScreenshot ;
static char s_sScreenshotName [ 1024 ] ;
static LPDIRECT3DSURFACE9 ScreenShootMEMSurface = NULL ;
2009-11-08 20:35:11 +00:00
2009-10-10 23:36:18 +00:00
// State translation lookup tables
static const D3DBLEND d3dSrcFactors [ 8 ] =
{
D3DBLEND_ZERO ,
D3DBLEND_ONE ,
D3DBLEND_DESTCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_SRCALPHA ,
D3DBLEND_INVSRCALPHA ,
D3DBLEND_DESTALPHA ,
D3DBLEND_INVDESTALPHA
} ;
static const D3DBLEND d3dDestFactors [ 8 ] =
{
D3DBLEND_ZERO ,
D3DBLEND_ONE ,
D3DBLEND_SRCCOLOR ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_SRCALPHA ,
D3DBLEND_INVSRCALPHA ,
D3DBLEND_DESTALPHA ,
D3DBLEND_INVDESTALPHA
} ;
2010-09-28 02:15:02 +00:00
// 0 0x00
// 1 Source & destination
// 2 Source & ~destination
// 3 Source
// 4 ~Source & destination
// 5 Destination
// 6 Source ^ destination = Source & ~destination | ~Source & destination
// 7 Source | destination
// 8 ~(Source | destination)
// 9 ~(Source ^ destination) = ~Source & ~destination | Source & destination
// 10 ~Destination
// 11 Source | ~destination
// 12 ~Source
// 13 ~Source | destination
// 14 ~(Source & destination)
// 15 0xff
2010-06-05 01:38:22 +00:00
static const D3DBLENDOP d3dLogicOpop [ 16 ] =
2009-12-07 18:48:31 +00:00
{
2010-06-05 00:01:18 +00:00
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD ,
D3DBLENDOP_SUBTRACT ,
D3DBLENDOP_ADD ,
D3DBLENDOP_REVSUBTRACT ,
D3DBLENDOP_ADD ,
D3DBLENDOP_MAX ,
D3DBLENDOP_ADD ,
2009-12-07 18:48:31 +00:00
2010-06-05 00:01:18 +00:00
D3DBLENDOP_MAX ,
D3DBLENDOP_MAX ,
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD ,
D3DBLENDOP_ADD
2009-12-07 18:48:31 +00:00
} ;
static const D3DBLEND d3dLogicOpSrcFactors [ 16 ] =
{
2010-06-05 00:01:18 +00:00
D3DBLEND_ZERO ,
D3DBLEND_DESTCOLOR ,
D3DBLEND_ONE ,
D3DBLEND_ONE ,
D3DBLEND_DESTCOLOR ,
D3DBLEND_ZERO ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_ONE ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_ONE
2009-12-07 18:48:31 +00:00
} ;
static const D3DBLEND d3dLogicOpDestFactors [ 16 ] =
{
2010-06-05 00:01:18 +00:00
D3DBLEND_ZERO ,
D3DBLEND_ZERO ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_ZERO ,
D3DBLEND_ONE ,
D3DBLEND_ONE ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_ONE ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_SRCCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_INVDESTCOLOR ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_ONE ,
D3DBLEND_INVSRCCOLOR ,
D3DBLEND_ONE
2009-12-07 18:48:31 +00:00
} ;
2009-11-23 14:08:08 +00:00
2010-07-06 13:14:51 +00:00
static const D3DCULL d3dCullModes [ 4 ] =
2009-11-23 14:08:08 +00:00
{
D3DCULL_NONE ,
D3DCULL_CCW ,
D3DCULL_CW ,
D3DCULL_CCW
} ;
2010-07-06 13:14:51 +00:00
static const D3DCMPFUNC d3dCmpFuncs [ 8 ] =
2009-11-23 14:08:08 +00:00
{
D3DCMP_NEVER ,
D3DCMP_LESS ,
D3DCMP_EQUAL ,
D3DCMP_LESSEQUAL ,
D3DCMP_GREATER ,
D3DCMP_NOTEQUAL ,
D3DCMP_GREATEREQUAL ,
D3DCMP_ALWAYS
} ;
2010-07-06 13:14:51 +00:00
static const D3DTEXTUREFILTERTYPE d3dMipFilters [ 4 ] =
2009-11-27 19:42:27 +00:00
{
D3DTEXF_NONE ,
D3DTEXF_POINT ,
D3DTEXF_LINEAR ,
2010-04-22 02:51:07 +00:00
D3DTEXF_NONE , //reserved
2009-11-27 19:42:27 +00:00
} ;
2009-11-23 14:08:08 +00:00
2009-11-27 19:42:27 +00:00
static const D3DTEXTUREADDRESS d3dClamps [ 4 ] =
{
D3DTADDRESS_CLAMP ,
D3DTADDRESS_WRAP ,
D3DTADDRESS_MIRROR ,
D3DTADDRESS_WRAP //reserved
} ;
2009-11-23 14:08:08 +00:00
2009-09-13 17:46:33 +00:00
void SetupDeviceObjects ( )
{
D3D : : font . Init ( ) ;
VertexLoaderManager : : Init ( ) ;
2010-09-28 02:15:02 +00:00
g_framebufferManager . Create ( ) ;
2009-09-15 21:05:31 +00:00
2009-09-15 21:49:15 +00:00
VertexShaderManager : : Dirty ( ) ;
PixelShaderManager : : Dirty ( ) ;
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
TextureConverter : : Init ( ) ;
2010-06-19 16:22:24 +00:00
// To avoid shader compilation stutters, read back all shaders from cache.
VertexShaderCache : : Init ( ) ;
PixelShaderCache : : Init ( ) ;
// Texture cache will recreate themselves over time.
2009-09-13 17:46:33 +00:00
}
// Kill off all POOL_DEFAULT device objects.
void TeardownDeviceObjects ( )
{
2010-01-28 04:30:07 +00:00
if ( ScreenShootMEMSurface )
ScreenShootMEMSurface - > Release ( ) ;
ScreenShootMEMSurface = NULL ;
2009-09-15 19:53:22 +00:00
D3D : : dev - > SetRenderTarget ( 0 , D3D : : GetBackBufferSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( D3D : : GetBackBufferDepthSurface ( ) ) ;
2010-09-28 02:15:02 +00:00
g_framebufferManager . Destroy ( ) ;
2009-09-13 17:46:33 +00:00
D3D : : font . Shutdown ( ) ;
TextureCache : : Invalidate ( false ) ;
VertexLoaderManager : : Shutdown ( ) ;
2010-06-19 16:22:24 +00:00
VertexShaderCache : : Shutdown ( ) ;
PixelShaderCache : : Shutdown ( ) ;
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
TextureConverter : : Shutdown ( ) ;
2009-09-13 17:46:33 +00:00
}
2010-09-28 02:15:02 +00:00
// Init functions
bool Renderer : : Init ( )
2008-12-08 05:25:12 +00:00
{
2010-06-20 22:23:34 +00:00
st = new char [ 32768 ] ;
2009-09-13 08:21:35 +00:00
UpdateActiveConfig ( ) ;
2010-04-22 04:28:34 +00:00
int fullScreenRes , x , y , w_temp , h_temp ;
2010-01-28 13:38:09 +00:00
s_blendMode = 0 ;
2010-06-05 00:01:18 +00:00
// Multisample Anti-aliasing hasn't been implemented yet use supersamling instead
int backbuffer_ms_mode = 0 ;
2009-09-15 08:13:45 +00:00
2010-04-22 04:28:34 +00:00
g_VideoInitialize . pRequestWindowSize ( x , y , w_temp , h_temp ) ;
2009-09-15 08:13:45 +00:00
2009-11-08 02:28:06 +00:00
for ( fullScreenRes = 0 ; fullScreenRes < ( int ) D3D : : GetAdapter ( g_ActiveConfig . iAdapter ) . resolutions . size ( ) ; fullScreenRes + + )
2009-09-15 08:13:45 +00:00
{
2009-09-17 05:07:16 +00:00
if ( ( D3D : : GetAdapter ( g_ActiveConfig . iAdapter ) . resolutions [ fullScreenRes ] . xres = = w_temp ) & &
( D3D : : GetAdapter ( g_ActiveConfig . iAdapter ) . resolutions [ fullScreenRes ] . yres = = h_temp ) )
2009-09-15 08:13:45 +00:00
break ;
}
2009-09-17 05:57:38 +00:00
if ( fullScreenRes = = D3D : : GetAdapter ( g_ActiveConfig . iAdapter ) . resolutions . size ( ) )
fullScreenRes = 0 ;
2010-07-06 13:14:51 +00:00
D3D : : Create ( g_ActiveConfig . iAdapter , EmuWindow : : GetWnd ( ) ,
2009-09-15 19:53:22 +00:00
fullScreenRes , backbuffer_ms_mode , false ) ;
2008-12-08 05:25:12 +00:00
2010-02-04 22:25:09 +00:00
IS_AMD = D3D : : IsATIDevice ( ) ;
2010-09-28 02:15:02 +00:00
// Decide frambuffer size
2009-09-13 17:46:33 +00:00
s_backbuffer_width = D3D : : GetBackBufferWidth ( ) ;
s_backbuffer_height = D3D : : GetBackBufferHeight ( ) ;
2009-03-01 01:09:32 +00:00
2010-03-14 18:57:50 +00:00
s_XFB_width = MAX_XFB_WIDTH ;
s_XFB_height = MAX_XFB_HEIGHT ;
TargetRectangle dst_rect ;
ComputeDrawRectangle ( s_backbuffer_width , s_backbuffer_height , false , & dst_rect ) ;
if ( g_ActiveConfig . bUseRealXFB )
{
2010-09-30 15:24:34 +00:00
xScale = 1.0f ;
yScale = 1.0f ;
2010-03-14 18:57:50 +00:00
}
else
{
xScale = ( float ) ( dst_rect . right - dst_rect . left ) / ( float ) s_XFB_width ;
yScale = ( float ) ( dst_rect . bottom - dst_rect . top ) / ( float ) s_XFB_height ;
}
2010-06-09 15:33:01 +00:00
s_LastAA = g_ActiveConfig . iMultisampleMode ;
s_LastEFBScale = g_ActiveConfig . iEFBScale ;
2010-07-06 13:14:51 +00:00
float SupersampleCoeficient = s_LastAA + 1 ;
2010-06-09 15:33:01 +00:00
switch ( s_LastEFBScale )
{
2010-07-06 13:14:51 +00:00
case 0 :
2010-06-09 15:33:01 +00:00
EFBxScale = xScale ;
EFByScale = yScale ;
break ;
2010-07-06 13:14:51 +00:00
case 1 :
2010-06-09 15:33:01 +00:00
EFBxScale = ceilf ( xScale ) ;
EFByScale = ceilf ( yScale ) ;
break ;
default :
EFBxScale = g_ActiveConfig . iEFBScale - 1 ;
EFByScale = EFBxScale ;
break ;
} ;
2010-02-03 22:19:00 +00:00
2010-06-09 15:33:01 +00:00
EFBxScale * = SupersampleCoeficient ;
EFByScale * = SupersampleCoeficient ;
2010-05-19 03:15:36 +00:00
s_target_width = EFB_WIDTH * EFBxScale ;
s_target_height = EFB_HEIGHT * EFByScale ;
2010-01-21 22:32:24 +00:00
s_Fulltarget_width = s_target_width ;
2010-02-25 06:12:35 +00:00
s_Fulltarget_height = s_target_height ;
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
2010-09-28 02:15:02 +00:00
s_bLastFrameDumped = false ;
s_bAVIDumping = false ;
2009-03-28 21:07:16 +00:00
2010-04-03 22:22:55 +00:00
// We're not using fixed function.
2009-09-03 19:24:16 +00:00
// Let's just set the matrices to identity to be sure.
2009-02-28 22:10:38 +00:00
D3DXMATRIX mtx ;
D3DXMatrixIdentity ( & mtx ) ;
D3D : : dev - > SetTransform ( D3DTS_VIEW , & mtx ) ;
D3D : : dev - > SetTransform ( D3DTS_WORLD , & mtx ) ;
2009-09-13 17:46:33 +00:00
SetupDeviceObjects ( ) ;
2009-09-03 20:37:35 +00:00
2009-09-15 21:05:31 +00:00
for ( int stage = 0 ; stage < 8 ; stage + + )
D3D : : SetSamplerState ( stage , D3DSAMP_MAXANISOTROPY , g_ActiveConfig . iMaxAnisotropy ) ;
2010-01-17 17:44:09 +00:00
2009-11-08 20:35:11 +00:00
D3DVIEWPORT9 vp ;
vp . X = 0 ;
vp . Y = 0 ;
vp . Width = s_backbuffer_width ;
vp . Height = s_backbuffer_height ;
vp . MinZ = 0.0f ;
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
vp . MaxZ = 1.0f ;
2009-11-08 20:35:11 +00:00
D3D : : dev - > SetViewport ( & vp ) ;
2009-09-13 17:46:33 +00:00
D3D : : dev - > Clear ( 0 , NULL , D3DCLEAR_TARGET , 0x0 , 0 , 0 ) ;
2009-11-08 20:35:11 +00:00
2010-09-28 02:15:02 +00:00
D3D : : dev - > SetRenderTarget ( 0 , g_framebufferManager . GetEFBColorRTSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( g_framebufferManager . GetEFBDepthRTSurface ( ) ) ;
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
vp . X = ( s_Fulltarget_width - s_target_width ) / 2 ;
vp . Y = ( s_Fulltarget_height - s_target_height ) / 2 ;
2009-11-08 20:35:11 +00:00
vp . Width = s_target_width ;
vp . Height = s_target_height ;
D3D : : dev - > SetViewport ( & vp ) ;
2009-10-02 21:23:56 +00:00
D3D : : dev - > Clear ( 0 , NULL , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , 0x0 , 1.0f , 0 ) ;
2009-09-13 17:46:33 +00:00
D3D : : BeginFrame ( ) ;
2009-10-30 04:14:43 +00:00
D3D : : SetRenderState ( D3DRS_SCISSORTESTENABLE , true ) ;
2010-07-09 20:56:16 +00:00
D3D : : dev - > CreateOffscreenPlainSurface ( s_backbuffer_width , s_backbuffer_height , D3DFMT_X8R8G8B8 , D3DPOOL_SYSTEMMEM , & ScreenShootMEMSurface , NULL ) ;
2009-09-03 20:37:35 +00:00
return true ;
2008-12-08 05:25:12 +00:00
}
2009-02-28 22:10:38 +00:00
void Renderer : : Shutdown ( )
2008-12-08 05:25:12 +00:00
{
2009-09-13 17:46:33 +00:00
TeardownDeviceObjects ( ) ;
2008-12-08 05:25:12 +00:00
D3D : : EndFrame ( ) ;
2009-09-20 03:29:43 +00:00
D3D : : Present ( ) ;
2008-12-08 05:25:12 +00:00
D3D : : Close ( ) ;
2010-02-25 06:12:35 +00:00
2010-09-28 02:15:02 +00:00
if ( s_bAVIDumping )
2009-09-03 20:37:35 +00:00
{
2009-03-28 21:07:16 +00:00
AVIDump : : Stop ( ) ;
}
2010-06-20 22:23:34 +00:00
delete [ ] st ;
2008-12-08 05:25:12 +00:00
}
2010-09-28 02:15:02 +00:00
// Return the rendering target width and height
int Renderer : : GetTargetWidth ( )
{
return s_target_width ;
}
2010-05-19 03:15:36 +00:00
2010-09-28 02:15:02 +00:00
int Renderer : : GetTargetHeight ( )
{
return s_target_height ;
}
int Renderer : : GetFullTargetWidth ( )
{
return s_Fulltarget_width ;
}
2010-05-19 03:15:36 +00:00
2010-09-28 02:15:02 +00:00
int Renderer : : GetFullTargetHeight ( )
{
return s_Fulltarget_height ;
}
float Renderer : : GetTargetScaleX ( )
{
return EFBxScale ;
}
float Renderer : : GetTargetScaleY ( )
{
return EFByScale ;
}
2008-12-08 05:25:12 +00:00
2010-09-28 02:15:02 +00:00
float Renderer : : GetXFBScaleX ( )
{
return xScale ;
}
float Renderer : : GetXFBScaleY ( )
{
return yScale ;
}
2010-01-29 07:44:21 +00:00
// Create On-Screen-Messages
void Renderer : : DrawDebugText ( )
{
2010-09-30 15:24:34 +00:00
// OSD Menu messages
2010-01-29 07:44:21 +00:00
if ( g_ActiveConfig . bOSDHotKey )
{
if ( OSDChoice > 0 )
{
OSDTime = Common : : Timer : : GetTimeMs ( ) + 3000 ;
OSDChoice = - OSDChoice ;
}
if ( ( u32 ) OSDTime > Common : : Timer : : GetTimeMs ( ) )
{
std : : string T1 = " " , T2 = " " ;
std : : vector < std : : string > T0 ;
2010-09-30 15:24:34 +00:00
std : : string OSDM1 ;
switch ( g_ActiveConfig . iEFBScale )
{
case 0 :
OSDM1 = " Auto (fractional) " ;
break ;
case 1 :
OSDM1 = " Auto (integral) " ;
break ;
case 2 :
OSDM1 = " Native " ;
break ;
case 3 :
OSDM1 = " 2x " ;
break ;
case 4 :
OSDM1 = " 3x " ;
break ;
}
2010-01-29 07:44:21 +00:00
std : : string OSDM21 ;
switch ( g_ActiveConfig . iAspectRatio )
{
case ASPECT_AUTO :
OSDM21 = " Auto " ;
break ;
case ASPECT_FORCE_16_9 :
OSDM21 = " 16:9 " ;
break ;
case ASPECT_FORCE_4_3 :
OSDM21 = " 4:3 " ;
break ;
case ASPECT_STRETCH :
OSDM21 = " Stretch " ;
break ;
}
std : : string OSDM22 =
2010-02-25 06:12:35 +00:00
g_ActiveConfig . bCrop ? " (crop) " : " " ;
2010-01-29 07:44:21 +00:00
std : : string OSDM3 = g_ActiveConfig . bEFBCopyDisable ? " Disabled " :
g_ActiveConfig . bCopyEFBToTexture ? " To Texture " : " To RAM " ;
2010-09-28 02:15:02 +00:00
// If there is more text than this we will have a collision
2010-01-29 07:44:21 +00:00
if ( g_ActiveConfig . bShowFPS )
2010-09-28 02:15:02 +00:00
{
T1 + = " \n \n " ;
T2 + = " \n \n " ;
}
2010-01-29 07:44:21 +00:00
// The rows
T0 . push_back ( StringFromFormat ( " 3: Internal Resolution: %s \n " , OSDM1 . c_str ( ) ) ) ;
T0 . push_back ( StringFromFormat ( " 4: Aspect Ratio: %s%s \n " , OSDM21 . c_str ( ) , OSDM22 . c_str ( ) ) ) ;
T0 . push_back ( StringFromFormat ( " 5: Copy EFB: %s \n " , OSDM3 . c_str ( ) ) ) ;
T0 . push_back ( StringFromFormat ( " 6: Fog: %s \n " , g_ActiveConfig . bDisableFog ? " Disabled " : " Enabled " ) ) ;
2010-07-06 13:14:51 +00:00
T0 . push_back ( StringFromFormat ( " 7: Material Lighting: %s \n " , g_ActiveConfig . bDisableLighting ? " Disabled " : " Enabled " ) ) ;
2010-01-29 07:44:21 +00:00
// The latest changed setting in yellow
T1 + = ( OSDChoice = = - 1 ) ? T0 . at ( 0 ) : " \n " ;
T1 + = ( OSDChoice = = - 2 ) ? T0 . at ( 1 ) : " \n " ;
T1 + = ( OSDChoice = = - 3 ) ? T0 . at ( 2 ) : " \n " ;
T1 + = ( OSDChoice = = - 4 ) ? T0 . at ( 3 ) : " \n " ;
2010-02-25 06:12:35 +00:00
T1 + = ( OSDChoice = = - 5 ) ? T0 . at ( 4 ) : " \n " ;
2010-01-29 07:44:21 +00:00
// The other settings in cyan
T2 + = ( OSDChoice ! = - 1 ) ? T0 . at ( 0 ) : " \n " ;
T2 + = ( OSDChoice ! = - 2 ) ? T0 . at ( 1 ) : " \n " ;
T2 + = ( OSDChoice ! = - 3 ) ? T0 . at ( 2 ) : " \n " ;
T2 + = ( OSDChoice ! = - 4 ) ? T0 . at ( 3 ) : " \n " ;
2010-02-25 06:12:35 +00:00
T2 + = ( OSDChoice ! = - 5 ) ? T0 . at ( 4 ) : " \n " ;
2010-01-29 07:44:21 +00:00
// Render a shadow, and then the text
Renderer : : RenderText ( T1 . c_str ( ) , 21 , 21 , 0xDD000000 ) ;
Renderer : : RenderText ( T1 . c_str ( ) , 20 , 20 , 0xFFffff00 ) ;
Renderer : : RenderText ( T2 . c_str ( ) , 21 , 21 , 0xDD000000 ) ;
Renderer : : RenderText ( T2 . c_str ( ) , 20 , 20 , 0xFF00FFFF ) ;
}
}
}
2009-09-03 19:42:45 +00:00
void Renderer : : RenderText ( const char * text , int left , int top , u32 color )
2008-12-08 05:25:12 +00:00
{
2009-09-03 19:42:45 +00:00
D3D : : font . DrawTextScaled ( ( float ) left , ( float ) top , 20 , 20 , 0.0f , color , text , false ) ;
2008-12-08 05:25:12 +00:00
}
2009-09-03 21:56:08 +00:00
TargetRectangle Renderer : : ConvertEFBRectangle ( const EFBRectangle & rc )
{
2010-09-30 15:24:34 +00:00
TargetRectangle result ;
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
int Xstride = ( s_Fulltarget_width - s_target_width ) / 2 ;
int Ystride = ( s_Fulltarget_height - s_target_height ) / 2 ;
2010-05-19 03:15:36 +00:00
result . left = ( int ) ( rc . left * EFBxScale ) + Xstride ;
result . top = ( int ) ( rc . top * EFByScale ) + Ystride ;
result . right = ( int ) ( rc . right * EFBxScale ) + Xstride ;
result . bottom = ( int ) ( rc . bottom * EFByScale ) + Ystride ;
2009-09-03 21:56:08 +00:00
return result ;
}
2009-09-03 19:24:16 +00:00
void formatBufferDump ( const char * in , char * out , int w , int h , int p )
2009-03-28 21:07:16 +00:00
{
2009-09-03 21:56:08 +00:00
for ( int y = 0 ; y < h ; y + + )
{
2009-09-03 19:24:16 +00:00
const char * line = in + ( h - y - 1 ) * p ;
2009-09-03 21:56:08 +00:00
for ( int x = 0 ; x < w ; x + + )
{
2009-03-28 21:07:16 +00:00
memcpy ( out , line , 3 ) ;
out + = 3 ;
line + = 4 ;
2010-07-09 20:56:16 +00:00
}
2009-03-28 21:07:16 +00:00
}
}
2009-09-15 19:53:22 +00:00
// With D3D, we have to resize the backbuffer if the window changed
// size.
void CheckForResize ( )
{
while ( EmuWindow : : IsSizing ( ) )
Sleep ( 10 ) ;
2010-09-28 02:15:02 +00:00
2010-01-28 04:30:07 +00:00
if ( EmuWindow : : GetParentWnd ( ) )
{
// Re-stretch window to parent window size again, if it has a parent window.
RECT rcParentWindow ;
GetWindowRect ( EmuWindow : : GetParentWnd ( ) , & rcParentWindow ) ;
int width = rcParentWindow . right - rcParentWindow . left ;
int height = rcParentWindow . bottom - rcParentWindow . top ;
if ( width ! = s_backbuffer_width | | height ! = s_backbuffer_height )
2010-07-06 13:14:51 +00:00
MoveWindow ( EmuWindow : : GetWnd ( ) , 0 , 0 , width , height , FALSE ) ;
2010-01-28 04:30:07 +00:00
}
2009-09-15 19:53:22 +00:00
RECT rcWindow ;
GetClientRect ( EmuWindow : : GetWnd ( ) , & rcWindow ) ;
int client_width = rcWindow . right - rcWindow . left ;
int client_height = rcWindow . bottom - rcWindow . top ;
2010-09-28 02:15:02 +00:00
// Sanity check
2009-09-15 19:53:22 +00:00
if ( ( client_width ! = s_backbuffer_width | |
client_height ! = s_backbuffer_height ) & &
client_width > = 4 & & client_height > = 4 )
{
TeardownDeviceObjects ( ) ;
2010-07-06 13:14:51 +00:00
D3D : : Reset ( ) ;
2009-09-15 19:53:22 +00:00
s_backbuffer_width = D3D : : GetBackBufferWidth ( ) ;
s_backbuffer_height = D3D : : GetBackBufferHeight ( ) ;
2010-07-09 20:56:16 +00:00
if ( ScreenShootMEMSurface )
ScreenShootMEMSurface - > Release ( ) ;
D3D : : dev - > CreateOffscreenPlainSurface ( s_backbuffer_width , s_backbuffer_height , D3DFMT_X8R8G8B8 , D3DPOOL_SYSTEMMEM , & ScreenShootMEMSurface , NULL ) ;
2010-03-14 18:57:50 +00:00
WindowResized = true ;
2009-09-15 19:53:22 +00:00
}
}
2009-09-20 05:04:45 +00:00
void Renderer : : RenderToXFB ( u32 xfbAddr , u32 fbWidth , u32 fbHeight , const EFBRectangle & sourceRc )
{
2010-07-06 13:14:51 +00:00
if ( ! fbWidth | | ! fbHeight )
2009-09-20 05:04:45 +00:00
return ;
2010-04-03 22:22:55 +00:00
VideoFifo_CheckEFBAccess ( ) ;
2010-09-28 02:15:02 +00:00
VideoFifo_CheckSwapRequestAt ( xfbAddr , fbWidth , fbHeight ) ;
2010-05-19 03:15:36 +00:00
XFBWrited = true ;
// XXX: Without the VI, how would we know what kind of field this is? So
// just use progressive.
2010-07-02 17:09:53 +00:00
if ( g_ActiveConfig . bUseXFB )
2010-03-14 18:57:50 +00:00
{
2010-09-28 02:15:02 +00:00
g_framebufferManager . CopyToXFB ( xfbAddr , fbWidth , fbHeight , sourceRc ) ;
2010-07-02 17:09:53 +00:00
}
else
{
Renderer : : Swap ( xfbAddr , FIELD_PROGRESSIVE , fbWidth , fbHeight , sourceRc ) ;
2010-03-14 18:57:50 +00:00
Common : : AtomicStoreRelease ( s_swapRequested , FALSE ) ;
}
2008-12-08 05:25:12 +00:00
}
2009-09-03 19:42:45 +00:00
bool Renderer : : SetScissorRect ( )
2008-12-08 05:25:12 +00:00
{
2009-06-22 09:31:30 +00:00
int xoff = bpmem . scissorOffset . x * 2 - 342 ;
int yoff = bpmem . scissorOffset . y * 2 - 342 ;
2009-03-08 18:45:39 +00:00
RECT rc ;
2009-06-22 09:31:30 +00:00
rc . left = ( int ) ( ( float ) bpmem . scissorTL . x - xoff - 342 ) ;
rc . top = ( int ) ( ( float ) bpmem . scissorTL . y - yoff - 342 ) ;
rc . right = ( int ) ( ( float ) bpmem . scissorBR . x - xoff - 341 ) ;
rc . bottom = ( int ) ( ( float ) bpmem . scissorBR . y - yoff - 341 ) ;
2009-03-08 18:45:39 +00:00
2009-09-13 17:46:33 +00:00
if ( rc . left < 0 ) rc . left = 0 ;
2009-11-08 20:35:11 +00:00
if ( rc . right < 0 ) rc . right = 0 ;
2010-06-05 00:01:18 +00:00
if ( rc . left > EFB_WIDTH ) rc . left = EFB_WIDTH ;
if ( rc . right > EFB_WIDTH ) rc . right = EFB_WIDTH ;
2009-09-13 17:46:33 +00:00
if ( rc . top < 0 ) rc . top = 0 ;
2009-11-08 20:35:11 +00:00
if ( rc . bottom < 0 ) rc . bottom = 0 ;
2010-06-05 00:01:18 +00:00
if ( rc . top > EFB_HEIGHT ) rc . top = EFB_HEIGHT ;
if ( rc . bottom > EFB_HEIGHT ) rc . bottom = EFB_HEIGHT ;
2010-02-05 03:37:11 +00:00
2010-01-17 17:44:09 +00:00
if ( rc . left > rc . right )
2009-11-23 14:08:08 +00:00
{
int temp = rc . right ;
rc . right = rc . left ;
rc . left = temp ;
}
2010-01-17 17:44:09 +00:00
if ( rc . top > rc . bottom )
2009-11-23 14:08:08 +00:00
{
int temp = rc . bottom ;
rc . bottom = rc . top ;
rc . top = temp ;
}
2010-06-05 00:01:18 +00:00
int Xstride = ( s_Fulltarget_width - s_target_width ) / 2 ;
int Ystride = ( s_Fulltarget_height - s_target_height ) / 2 ;
rc . left = ( int ) ( rc . left * EFBxScale ) + Xstride ;
rc . top = ( int ) ( rc . top * EFByScale ) + Ystride ;
rc . right = ( int ) ( rc . right * EFBxScale ) + Xstride ;
2010-07-06 13:14:51 +00:00
rc . bottom = ( int ) ( rc . bottom * EFByScale ) + Ystride ;
2010-06-05 00:01:18 +00:00
2010-09-30 15:24:34 +00:00
// Check that the coordinates are good
2010-06-05 00:01:18 +00:00
if ( rc . right ! = rc . left & & rc . bottom ! = rc . top )
2009-09-13 08:21:35 +00:00
{
2008-12-08 05:25:12 +00:00
D3D : : dev - > SetScissorRect ( & rc ) ;
2009-09-03 19:42:45 +00:00
return true ;
}
2008-12-08 05:25:12 +00:00
else
2009-09-03 19:42:45 +00:00
{
2009-11-23 14:08:08 +00:00
//WARN_LOG(VIDEO, "Bad scissor rectangle: %i %i %i %i", rc.left, rc.top, rc.right, rc.bottom);
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
rc . left = Xstride ;
rc . top = Ystride ;
2010-02-04 22:25:09 +00:00
rc . right = Xstride + s_target_width ;
rc . bottom = Ystride + s_target_height ;
2009-11-22 02:37:00 +00:00
D3D : : dev - > SetScissorRect ( & rc ) ;
2009-09-03 19:42:45 +00:00
}
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
return false ;
2009-09-03 19:42:45 +00:00
}
2010-09-28 02:15:02 +00:00
void Renderer : : SetColorMask ( )
2009-09-03 19:42:45 +00:00
{
2009-09-13 08:21:35 +00:00
DWORD color_mask = 0 ;
2010-07-06 13:14:51 +00:00
if ( bpmem . blendmode . alphaupdate )
2009-09-13 08:21:35 +00:00
color_mask = D3DCOLORWRITEENABLE_ALPHA ;
2010-07-06 13:14:51 +00:00
if ( bpmem . blendmode . colorupdate )
2009-09-13 08:21:35 +00:00
color_mask | = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE ;
D3D : : SetRenderState ( D3DRS_COLORWRITEENABLE , color_mask ) ;
2008-12-08 05:25:12 +00:00
}
2009-09-04 17:29:16 +00:00
u32 Renderer : : AccessEFB ( EFBAccessType type , int x , int y )
{
2010-01-17 17:44:09 +00:00
if ( ! g_ActiveConfig . bEFBAccessEnable )
2009-12-28 19:13:06 +00:00
return 0 ;
2010-07-16 21:51:35 +00:00
if ( type = = POKE_Z | | type = = POKE_COLOR )
{
static bool alert_only_once = true ;
if ( ! alert_only_once ) return 0 ;
PanicAlert ( " Poke EFB not implemented " ) ;
alert_only_once = false ;
return 0 ;
}
2010-07-06 13:14:51 +00:00
// Get the working buffer
2009-10-06 14:24:10 +00:00
LPDIRECT3DSURFACE9 pBuffer = ( type = = PEEK_Z | | type = = POKE_Z ) ?
2010-09-28 02:15:02 +00:00
g_framebufferManager . GetEFBDepthRTSurface ( ) : g_framebufferManager . GetEFBColorRTSurface ( ) ;
2010-07-06 13:14:51 +00:00
// Get the temporal buffer to move 1pixel data
2009-10-10 23:36:18 +00:00
LPDIRECT3DSURFACE9 RBuffer = ( type = = PEEK_Z | | type = = POKE_Z ) ?
2010-09-28 02:15:02 +00:00
g_framebufferManager . GetEFBDepthReadSurface ( ) : g_framebufferManager . GetEFBColorReadSurface ( ) ;
2010-07-06 13:14:51 +00:00
// Get the memory buffer that can be locked
2009-10-08 00:35:47 +00:00
LPDIRECT3DSURFACE9 pOffScreenBuffer = ( type = = PEEK_Z | | type = = POKE_Z ) ?
2010-09-28 02:15:02 +00:00
g_framebufferManager . GetEFBDepthOffScreenRTSurface ( ) : g_framebufferManager . GetEFBColorOffScreenRTSurface ( ) ;
2010-07-06 13:14:51 +00:00
// Get the buffer format
2009-10-06 14:24:10 +00:00
D3DFORMAT BufferFormat = ( type = = PEEK_Z | | type = = POKE_Z ) ?
2010-09-28 02:15:02 +00:00
g_framebufferManager . GetEFBDepthRTSurfaceFormat ( ) : g_framebufferManager . GetEFBColorRTSurfaceFormat ( ) ;
2009-11-22 02:37:00 +00:00
D3DFORMAT ReadBufferFormat = ( type = = PEEK_Z | | type = = POKE_Z ) ?
2010-09-28 02:15:02 +00:00
g_framebufferManager . GetEFBDepthReadSurfaceFormat ( ) : BufferFormat ;
2009-10-10 23:36:18 +00:00
2010-01-17 17:44:09 +00:00
if ( BufferFormat = = D3DFMT_D24X8 )
2009-11-10 12:45:03 +00:00
return 0 ;
2009-12-28 19:13:06 +00:00
D3DLOCKED_RECT drect ;
2009-10-10 23:36:18 +00:00
2010-07-06 13:14:51 +00:00
// Buffer not found alert
2010-01-17 17:44:09 +00:00
if ( ! pBuffer ) {
2009-10-06 14:24:10 +00:00
PanicAlert ( " No %s! " , ( type = = PEEK_Z | | type = = POKE_Z ) ? " Z-Buffer " : " Color EFB " ) ;
return 0 ;
}
2010-09-28 02:15:02 +00:00
// Get the rectangular target region covered by the EFB pixel
2009-09-04 17:29:16 +00:00
EFBRectangle efbPixelRc ;
efbPixelRc . left = x ;
efbPixelRc . top = y ;
efbPixelRc . right = x + 1 ;
efbPixelRc . bottom = y + 1 ;
2010-09-30 15:24:34 +00:00
TargetRectangle targetPixelRc = ConvertEFBRectangle ( efbPixelRc ) ;
2009-09-04 17:29:16 +00:00
2009-10-03 02:12:24 +00:00
u32 z = 0 ;
float val = 0.0f ;
HRESULT hr ;
RECT RectToLock ;
RectToLock . bottom = targetPixelRc . bottom ;
RectToLock . left = targetPixelRc . left ;
RectToLock . right = targetPixelRc . right ;
2009-11-22 02:37:00 +00:00
RectToLock . top = targetPixelRc . top ;
2010-01-17 17:44:09 +00:00
if ( type = = PEEK_Z )
2009-11-08 20:35:11 +00:00
{
2009-11-22 02:37:00 +00:00
RECT PixelRect ;
PixelRect . bottom = 4 ;
PixelRect . left = 0 ;
PixelRect . right = 4 ;
PixelRect . top = 0 ;
RectToLock . bottom + = 2 ;
RectToLock . right + = 1 ;
RectToLock . top - = 1 ;
RectToLock . left - = 2 ;
2010-01-17 17:44:09 +00:00
if ( ( RectToLock . bottom - RectToLock . top ) > 4 )
2009-11-22 02:37:00 +00:00
RectToLock . bottom - - ;
2010-01-17 17:44:09 +00:00
if ( ( RectToLock . right - RectToLock . left ) > 4 )
2009-11-22 02:37:00 +00:00
RectToLock . left + + ;
2010-09-28 02:15:02 +00:00
2010-07-06 13:14:51 +00:00
ResetAPIState ( ) ; // Reset any game specific settings
hr = D3D : : dev - > SetDepthStencilSurface ( NULL ) ;
2009-11-22 02:37:00 +00:00
hr = D3D : : dev - > SetRenderTarget ( 0 , RBuffer ) ;
2010-01-17 17:44:09 +00:00
if ( FAILED ( hr ) )
2009-11-10 12:45:03 +00:00
{
2009-11-22 02:37:00 +00:00
PanicAlert ( " unable to set pixel render buffer " ) ;
2009-11-10 12:45:03 +00:00
return 0 ;
}
2009-11-22 02:37:00 +00:00
D3DVIEWPORT9 vp ;
// Stretch picture with increased internal resolution
vp . X = 0 ;
vp . Y = 0 ;
vp . Width = 4 ;
vp . Height = 4 ;
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
hr = D3D : : dev - > SetViewport ( & vp ) ;
2010-01-17 17:44:09 +00:00
if ( FAILED ( hr ) )
2009-11-10 12:45:03 +00:00
{
2009-11-22 02:37:00 +00:00
PanicAlert ( " unable to set pixel viewport " ) ;
2009-11-10 12:45:03 +00:00
return 0 ;
}
2010-07-06 13:14:51 +00:00
float colmat [ 16 ] = { 0.0f } ;
2009-11-22 02:37:00 +00:00
float fConstAdd [ 4 ] = { 0.0f } ;
colmat [ 0 ] = colmat [ 5 ] = colmat [ 10 ] = 1.0f ;
PixelShaderManager : : SetColorMatrix ( colmat , fConstAdd ) ; // set transformation
EFBRectangle source_rect ;
2010-09-28 02:15:02 +00:00
LPDIRECT3DTEXTURE9 read_texture = g_framebufferManager . GetEFBDepthTexture ( source_rect ) ;
2009-11-22 02:37:00 +00:00
2010-07-06 13:14:51 +00:00
D3D : : ChangeSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_POINT ) ;
2009-11-22 02:37:00 +00:00
2010-02-08 23:23:04 +00:00
D3D : : drawShadedTexQuad (
2010-07-06 13:14:51 +00:00
read_texture ,
2010-02-08 23:23:04 +00:00
& RectToLock ,
2010-07-06 13:14:51 +00:00
Renderer : : GetFullTargetWidth ( ) ,
Renderer : : GetFullTargetHeight ( ) ,
4 , 4 ,
( BufferFormat = = FOURCC_RAWZ ) ? PixelShaderCache : : GetColorMatrixProgram ( 0 ) : PixelShaderCache : : GetDepthMatrixProgram ( 0 ) ,
2010-06-05 00:01:18 +00:00
VertexShaderCache : : GetSimpleVertexShader ( 0 ) ) ;
2009-11-22 02:37:00 +00:00
D3D : : RefreshSamplerState ( 0 , D3DSAMP_MINFILTER ) ;
2010-09-28 02:15:02 +00:00
hr = D3D : : dev - > SetRenderTarget ( 0 , g_framebufferManager . GetEFBColorRTSurface ( ) ) ;
hr = D3D : : dev - > SetDepthStencilSurface ( g_framebufferManager . GetEFBDepthRTSurface ( ) ) ;
2009-11-22 02:37:00 +00:00
RestoreAPIState ( ) ;
RectToLock . bottom = 4 ;
RectToLock . left = 0 ;
RectToLock . right = 4 ;
RectToLock . top = 0 ;
}
else
{
2010-07-06 13:14:51 +00:00
hr = D3D : : dev - > StretchRect ( pBuffer , & RectToLock , RBuffer , NULL , D3DTEXF_NONE ) ;
2009-11-10 12:45:03 +00:00
//change the rect to lock the entire one pixel buffer
RectToLock . bottom = 1 ;
RectToLock . left = 0 ;
RectToLock . right = 1 ;
RectToLock . top = 0 ;
2009-11-08 20:35:11 +00:00
}
2010-01-17 17:44:09 +00:00
if ( FAILED ( hr ) )
2009-11-22 02:37:00 +00:00
{
PanicAlert ( " Unable to stretch data to buffer " ) ;
return 0 ;
}
2010-07-06 13:14:51 +00:00
// Retrieve the pixel data to the local memory buffer
D3D : : dev - > GetRenderTargetData ( RBuffer , pOffScreenBuffer ) ;
2010-01-17 17:44:09 +00:00
if ( FAILED ( hr ) )
2009-11-22 02:37:00 +00:00
{
PanicAlert ( " Unable to copy data to mem buffer " ) ;
return 0 ;
}
2010-09-28 02:15:02 +00:00
2010-07-06 13:14:51 +00:00
// The surface is good.. lock it
2010-01-17 17:44:09 +00:00
if ( ( hr = pOffScreenBuffer - > LockRect ( & drect , & RectToLock , D3DLOCK_READONLY ) ) ! = D3D_OK )
2009-10-10 23:36:18 +00:00
{
2010-07-06 13:14:51 +00:00
PanicAlert ( " ERROR: %s " , hr = = D3DERR_WASSTILLDRAWING ? " Still drawing " : hr = = D3DERR_INVALIDCALL ? " Invalid call " : " w00t " ) ;
2009-10-10 23:36:18 +00:00
return 0 ;
}
2010-09-28 02:15:02 +00:00
switch ( type )
{
case PEEK_Z :
{
switch ( ReadBufferFormat )
2009-10-06 14:24:10 +00:00
{
2010-09-28 02:15:02 +00:00
case D3DFMT_R32F :
val = ( ( float * ) drect . pBits ) [ 6 ] ;
break ;
default :
float ffrac = 1.0f / 255.0f ;
z = ( ( u32 * ) drect . pBits ) [ 6 ] ;
val = ( ( float ) ( ( z > > 16 ) & 0xFF ) ) * ffrac ;
ffrac * = 1 / 255.0f ;
val + = ( ( float ) ( ( z > > 8 ) & 0xFF ) ) * ffrac ;
ffrac * = 1 / 255.0f ;
val + = ( ( float ) ( z & 0xFF ) ) * ffrac ;
break ;
} ;
z = ( ( u32 ) ( val * 0xffffff ) ) ;
}
break ;
2009-09-24 13:52:45 +00:00
2010-09-28 02:15:02 +00:00
case POKE_Z :
// TODO: Implement
break ;
case PEEK_COLOR :
z = ( ( u32 * ) drect . pBits ) [ 0 ] ;
break ;
case POKE_COLOR :
// TODO: Implement. One way is to draw a tiny pixel-sized rectangle at
// the exact location. Note: EFB pokes are susceptible to Z-buffering
// and perhaps blending.
//WARN_LOG(VIDEOINTERFACE, "This is probably some kind of software rendering");
break ;
2010-07-16 21:51:35 +00:00
// TODO: Implement POKE_Z and POKE_COLOR
2010-09-28 02:15:02 +00:00
default :
break ;
2009-09-04 17:29:16 +00:00
}
2010-07-06 13:14:51 +00:00
pOffScreenBuffer - > UnlockRect ( ) ;
2009-10-03 02:12:24 +00:00
// TODO: in RE0 this value is often off by one, which causes lighting to disappear
2009-10-10 23:36:18 +00:00
return z ;
2009-09-04 17:29:16 +00:00
}
2009-02-28 22:10:38 +00:00
// Called from VertexShaderManager
void UpdateViewport ( )
{
2009-11-23 14:08:08 +00:00
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
2010-02-25 06:12:35 +00:00
// [0] = width/2
// [1] = height/2
// [2] = 16777215 * (farz - nearz)
// [3] = xorig + width/2 + 342
// [4] = yorig + height/2 + 342
// [5] = 16777215 * farz
2010-07-11 16:26:46 +00:00
const int old_fulltarget_w = s_Fulltarget_width ;
const int old_fulltarget_h = s_Fulltarget_height ;
2009-09-03 19:24:16 +00:00
int scissorXOff = bpmem . scissorOffset . x * 2 ;
int scissorYOff = bpmem . scissorOffset . y * 2 ;
2009-02-28 22:10:38 +00:00
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
int Xstride = ( s_Fulltarget_width - s_target_width ) / 2 ;
int Ystride = ( s_Fulltarget_height - s_target_height ) / 2 ;
2009-09-02 04:10:40 +00:00
2009-09-03 19:24:16 +00:00
D3DVIEWPORT9 vp ;
2009-02-28 22:10:38 +00:00
2009-09-03 19:24:16 +00:00
// Stretch picture with increased internal resolution
2010-09-30 15:24:34 +00:00
int X = ( int ) ( ceil ( xfregs . rawViewport [ 3 ] - xfregs . rawViewport [ 0 ] - ( scissorXOff ) ) * EFBxScale ) + Xstride ;
int Y = ( int ) ( ceil ( xfregs . rawViewport [ 4 ] + xfregs . rawViewport [ 1 ] - ( scissorYOff ) ) * EFByScale ) + Ystride ;
int Width = ( int ) ceil ( 2.0f * xfregs . rawViewport [ 0 ] * EFBxScale ) ;
int Height = ( int ) ceil ( - 2.0f * xfregs . rawViewport [ 1 ] * EFByScale ) ;
2010-01-17 17:44:09 +00:00
if ( Width < 0 )
2009-11-23 14:08:08 +00:00
{
X + = Width ;
2010-02-25 06:12:35 +00:00
Width * = - 1 ;
2009-11-23 14:08:08 +00:00
}
2010-01-17 17:44:09 +00:00
if ( Height < 0 )
2009-11-23 14:08:08 +00:00
{
Y + = Height ;
2010-02-25 06:12:35 +00:00
Height * = - 1 ;
2009-11-23 14:08:08 +00:00
}
2010-02-03 22:19:00 +00:00
bool sizeChanged = false ;
2010-07-06 13:14:51 +00:00
if ( X < 0 )
2010-01-19 15:00:45 +00:00
{
2010-02-03 22:19:00 +00:00
s_Fulltarget_width - = 2 * X ;
X = 0 ;
sizeChanged = true ;
}
2010-07-06 13:14:51 +00:00
if ( Y < 0 )
2010-02-03 22:19:00 +00:00
{
s_Fulltarget_height - = 2 * Y ;
Y = 0 ;
2010-07-06 13:14:51 +00:00
sizeChanged = true ;
2010-02-03 22:19:00 +00:00
}
2010-07-06 13:14:51 +00:00
if ( ! IS_AMD )
2010-02-03 22:19:00 +00:00
{
2010-02-04 22:25:09 +00:00
if ( X + Width > s_Fulltarget_width )
{
s_Fulltarget_width + = ( X + Width - s_Fulltarget_width ) * 2 ;
2010-07-06 13:14:51 +00:00
sizeChanged = true ;
2010-02-04 22:25:09 +00:00
}
if ( Y + Height > s_Fulltarget_height )
{
s_Fulltarget_height + = ( Y + Height - s_Fulltarget_height ) * 2 ;
2010-07-06 13:14:51 +00:00
sizeChanged = true ;
2010-02-04 22:25:09 +00:00
}
2010-01-19 15:00:45 +00:00
}
2010-07-06 13:14:51 +00:00
if ( sizeChanged )
2010-02-03 22:19:00 +00:00
{
2010-07-11 16:26:46 +00:00
D3DCAPS9 caps = D3D : : GetCaps ( ) ;
// Make sure that the requested size is actually supported by the GFX driver
if ( s_Fulltarget_width > caps . MaxTextureWidth | | s_Fulltarget_height > caps . MaxTextureHeight )
{
2010-07-12 15:10:27 +00:00
// Skip EFB recreation and viewport setting. Most likely causes glitches in this case, but prevents crashes at least
ERROR_LOG ( VIDEO , " Tried to set a viewport which is too wide to emulate with Direct3D9. Requested EFB size is %dx%d, keeping the %dx%d EFB now \n " , s_Fulltarget_width , s_Fulltarget_height , old_fulltarget_w , old_fulltarget_h ) ;
// Fix the viewport to fit to the old EFB size, TODO: Check this for off-by-one errors
X * = old_fulltarget_w / s_Fulltarget_width ;
Y * = old_fulltarget_h / s_Fulltarget_height ;
Width * = old_fulltarget_w / s_Fulltarget_width ;
Height * = old_fulltarget_h / s_Fulltarget_height ;
2010-07-11 16:26:46 +00:00
s_Fulltarget_width = old_fulltarget_w ;
s_Fulltarget_height = old_fulltarget_h ;
}
2010-07-12 15:10:27 +00:00
else
{
D3D : : dev - > SetRenderTarget ( 0 , D3D : : GetBackBufferSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( D3D : : GetBackBufferDepthSurface ( ) ) ;
2010-09-28 02:15:02 +00:00
g_framebufferManager . Destroy ( ) ;
g_framebufferManager . Create ( ) ;
D3D : : dev - > SetRenderTarget ( 0 , g_framebufferManager . GetEFBColorRTSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( g_framebufferManager . GetEFBDepthRTSurface ( ) ) ;
2010-07-12 15:10:27 +00:00
}
2010-07-06 13:14:51 +00:00
}
Well this commit has 2 parts:
first part if fixing, fixed, i thing, the flickering that everyone has reported, at least in my case i only have flickering in the one texture in one game and now is fixed. The other fix is not for an reported issue, is more a correctness fix, running dolphin with pix to review debug errors, result in a ton of warnings and error, now with this commit, at least for ati, there no more error or warnings, this means, correct management and state change, no accurate emulation, for this still a lot of work to do.
for this part of the commit please give me feedback and let me know of remaining issues
Te second part is the partial implementation of efb to ram copy in d3d, this won't brake anything because is commented but i commit this to ask for help from ector and donko in some errors remaining in the implementation related to differences between opengl an d3d.
if you want to test this you have to uncomment line 150 to 155 of bpstruct.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4594 8ced0084-cf51-0410-be5f-012b33b47a6e
2009-11-20 18:46:30 +00:00
vp . X = X ;
vp . Y = Y ;
vp . Width = Width ;
vp . Height = Height ;
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
2010-07-06 13:14:51 +00:00
// Some games set invalids values for z min and z max so fix them to the max an min alowed and let the shaders do this work
vp . MinZ = 0.0f ; // (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777216.0f;
2010-07-12 15:10:27 +00:00
vp . MaxZ = 1.0f ; // xfregs.rawViewport[5] / 16777216.0f;
2009-02-28 22:10:38 +00:00
D3D : : dev - > SetViewport ( & vp ) ;
2009-09-02 04:10:40 +00:00
}
2009-09-20 03:29:43 +00:00
2009-10-02 21:23:56 +00:00
void Renderer : : ClearScreen ( const EFBRectangle & rc , bool colorEnable , bool alphaEnable , bool zEnable , u32 color , u32 z )
2010-07-06 13:14:51 +00:00
{
2009-11-22 02:37:00 +00:00
// Update the view port for clearing the picture
2010-09-30 15:24:34 +00:00
TargetRectangle targetRc = ConvertEFBRectangle ( rc ) ;
2010-02-25 06:12:35 +00:00
D3DVIEWPORT9 vp ;
2010-06-15 21:19:09 +00:00
vp . X = targetRc . left ;
2010-07-06 13:14:51 +00:00
vp . Y = targetRc . top ;
2010-06-15 21:19:09 +00:00
vp . Width = targetRc . GetWidth ( ) ;
vp . Height = targetRc . GetHeight ( ) ;
2009-11-22 02:37:00 +00:00
vp . MinZ = 0.0 ;
vp . MaxZ = 1.0 ;
2010-07-06 13:14:51 +00:00
D3D : : dev - > SetViewport ( & vp ) ;
2009-11-22 02:37:00 +00:00
// Always set the scissor in case it was set by the game and has not been reset
2010-07-06 13:14:51 +00:00
RECT sicr ;
sicr . left = targetRc . left ;
sicr . top = targetRc . top ;
sicr . right = targetRc . right ;
sicr . bottom = targetRc . bottom ;
D3D : : dev - > SetScissorRect ( & sicr ) ;
2010-06-19 21:12:09 +00:00
D3D : : ChangeRenderState ( D3DRS_ALPHABLENDENABLE , false ) ;
2010-01-17 17:44:09 +00:00
if ( zEnable )
2010-01-15 22:07:53 +00:00
D3D : : ChangeRenderState ( D3DRS_ZFUNC , D3DCMP_ALWAYS ) ;
2010-07-06 13:14:51 +00:00
D3D : : drawClearQuad ( color , ( z & 0xFFFFFF ) / float ( 0xFFFFFF ) , PixelShaderCache : : GetClearProgram ( ) , VertexShaderCache : : GetClearVertexShader ( ) ) ;
2010-01-17 17:44:09 +00:00
if ( zEnable )
2010-06-19 21:12:09 +00:00
D3D : : RefreshRenderState ( D3DRS_ZFUNC ) ;
D3D : : RefreshRenderState ( D3DRS_ALPHABLENDENABLE ) ;
2009-11-23 14:08:08 +00:00
UpdateViewport ( ) ;
2010-01-15 22:07:53 +00:00
SetScissorRect ( ) ;
2009-10-02 21:23:56 +00:00
}
2009-10-10 23:36:18 +00:00
void Renderer : : SetBlendMode ( bool forceUpdate )
2010-07-06 13:14:51 +00:00
{
2010-06-24 15:58:06 +00:00
if ( bpmem . blendmode . logicopenable )
2009-12-07 18:48:31 +00:00
return ;
2009-10-10 23:36:18 +00:00
2010-07-06 13:14:51 +00:00
if ( bpmem . blendmode . subtract & & bpmem . blendmode . blendenable )
2010-06-24 15:58:06 +00:00
{
D3D : : SetRenderState ( D3DRS_ALPHABLENDENABLE , true ) ;
D3D : : SetRenderState ( D3DRS_BLENDOP , D3DBLENDOP_REVSUBTRACT ) ;
D3D : : SetRenderState ( D3DRS_SRCBLEND , d3dSrcFactors [ 1 ] ) ;
D3D : : SetRenderState ( D3DRS_DESTBLEND , d3dDestFactors [ 1 ] ) ;
2010-07-06 13:14:51 +00:00
}
else
2010-06-24 15:58:06 +00:00
{
D3D : : SetRenderState ( D3DRS_ALPHABLENDENABLE , bpmem . blendmode . blendenable & & ( ! ( bpmem . blendmode . srcfactor = = 1 & & bpmem . blendmode . dstfactor = = 0 ) ) ) ;
2010-07-06 13:14:51 +00:00
if ( bpmem . blendmode . blendenable & & ( ! ( bpmem . blendmode . srcfactor = = 1 & & bpmem . blendmode . dstfactor = = 0 ) ) )
2010-06-24 15:58:06 +00:00
{
D3D : : SetRenderState ( D3DRS_BLENDOP , D3DBLENDOP_ADD ) ;
D3D : : SetRenderState ( D3DRS_SRCBLEND , d3dSrcFactors [ bpmem . blendmode . srcfactor ] ) ;
D3D : : SetRenderState ( D3DRS_DESTBLEND , d3dDestFactors [ bpmem . blendmode . dstfactor ] ) ;
2010-07-06 13:14:51 +00:00
}
}
2009-10-10 23:36:18 +00:00
}
2009-10-02 21:23:56 +00:00
2010-09-23 02:17:48 +00:00
static bool RightFrame = false ;
2010-09-28 02:15:02 +00:00
// This function has the final picture. We adjust the aspect ratio here.
2010-07-02 17:09:53 +00:00
void Renderer : : Swap ( u32 xfbAddr , FieldType field , u32 fbWidth , u32 fbHeight , const EFBRectangle & rc )
2009-09-20 03:29:43 +00:00
{
2010-05-19 03:15:36 +00:00
if ( g_bSkipCurrentFrame | | ( ! XFBWrited & & ! g_ActiveConfig . bUseRealXFB ) | | ! fbWidth | | ! fbHeight )
fixed fps limiting when using using virtual xfb, now fps = vps, in fact now real xfb is as fast as no using xfb, i'm thinking now that the correct thing is leave it enabled as default, and even remove the option.
the problem is one strange behavior i found, in opengl when xfb is enable, frame limit causes the frame rate to be limited exact half the correct speed, so if you choose auto and the game uses 30 fps you get 15 fps
so in opengl, you have to limit to the exact double of the game speed, 100 to pal games and 120 to ntsc.
in d3d this not happened every time, it just happen when you change some time consuming setting like changing the ssaa or resizing the window, in that case you have to disable and re enable frame limit to get the correct fps
to all the devs please if you can help me debug this, will give you a lot of thanks as i'm short in time to debug this error and is driving me crazy not to find the source of the problem.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5249 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-03-28 23:51:32 +00:00
{
2010-05-19 03:15:36 +00:00
g_VideoInitialize . pCopiedToXFB ( false ) ;
2010-03-14 18:57:50 +00:00
return ;
fixed fps limiting when using using virtual xfb, now fps = vps, in fact now real xfb is as fast as no using xfb, i'm thinking now that the correct thing is leave it enabled as default, and even remove the option.
the problem is one strange behavior i found, in opengl when xfb is enable, frame limit causes the frame rate to be limited exact half the correct speed, so if you choose auto and the game uses 30 fps you get 15 fps
so in opengl, you have to limit to the exact double of the game speed, 100 to pal games and 120 to ntsc.
in d3d this not happened every time, it just happen when you change some time consuming setting like changing the ssaa or resizing the window, in that case you have to disable and re enable frame limit to get the correct fps
to all the devs please if you can help me debug this, will give you a lot of thanks as i'm short in time to debug this error and is driving me crazy not to find the source of the problem.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5249 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-03-28 23:51:32 +00:00
}
2009-09-20 03:29:43 +00:00
// this function is called after the XFB field is changed, not after
// EFB is copied to XFB. In this way, flickering is reduced in games
2010-04-03 22:22:55 +00:00
// and seems to also give more FPS in ZTP
2010-09-28 02:15:02 +00:00
2010-04-14 13:57:16 +00:00
if ( field = = FIELD_LOWER ) xfbAddr - = fbWidth * 2 ;
2010-03-14 18:57:50 +00:00
u32 xfbCount = 0 ;
2010-09-28 02:15:02 +00:00
const XFBSource * * xfbSourceList = g_framebufferManager . GetXFBSource ( xfbAddr , fbWidth , fbHeight , xfbCount ) ;
2010-07-02 17:09:53 +00:00
if ( ( ! xfbSourceList | | xfbCount = = 0 ) & & g_ActiveConfig . bUseXFB & & ! g_ActiveConfig . bUseRealXFB )
2010-03-14 18:57:50 +00:00
{
2010-07-06 13:14:51 +00:00
g_VideoInitialize . pCopiedToXFB ( false ) ;
2010-03-14 18:57:50 +00:00
return ;
2010-07-06 13:14:51 +00:00
}
2010-03-14 18:57:50 +00:00
2010-09-30 15:24:34 +00:00
ResetAPIState ( ) ;
2010-09-23 02:17:48 +00:00
if ( g_ActiveConfig . bAnaglyphStereo )
{
if ( RightFrame )
{
D3D : : SetRenderState ( D3DRS_COLORWRITEENABLE , D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN ) ;
VertexShaderManager : : ResetView ( ) ;
VertexShaderManager : : TranslateView ( - 0.001f * g_ActiveConfig . iAnaglyphStereoSeparation , 0.0f ) ;
VertexShaderManager : : RotateView ( - 0.0001 * g_ActiveConfig . iAnaglyphFocalAngle , 0.0f ) ;
RightFrame = false ;
}
else
{
D3D : : SetRenderState ( D3DRS_COLORWRITEENABLE , D3DCOLORWRITEENABLE_RED ) ;
VertexShaderManager : : ResetView ( ) ;
VertexShaderManager : : TranslateView ( 0.001f * g_ActiveConfig . iAnaglyphStereoSeparation , 0.0f ) ;
VertexShaderManager : : RotateView ( 0.0001 * g_ActiveConfig . iAnaglyphFocalAngle , 0.0f ) ;
RightFrame = true ;
}
}
2010-09-28 02:15:02 +00:00
// Prepare to copy the XFBs to our backbuffer
2010-03-14 18:57:50 +00:00
D3D : : dev - > SetDepthStencilSurface ( NULL ) ;
D3D : : dev - > SetRenderTarget ( 0 , D3D : : GetBackBufferSurface ( ) ) ;
TargetRectangle dst_rect ;
ComputeDrawRectangle ( s_backbuffer_width , s_backbuffer_height , false , & dst_rect ) ;
D3DVIEWPORT9 vp ;
2010-09-30 15:24:34 +00:00
// Clear full target screen (edges, borders etc)
2010-03-14 18:57:50 +00:00
vp . X = 0 ;
vp . Y = 0 ;
vp . Width = s_backbuffer_width ;
vp . Height = s_backbuffer_height ;
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
D3D : : dev - > SetViewport ( & vp ) ;
2010-09-23 02:17:48 +00:00
//D3D::dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
D3D : : drawClearQuad ( 0 , 1.0 , PixelShaderCache : : GetClearProgram ( ) , VertexShaderCache : : GetClearVertexShader ( ) ) ;
2010-03-14 18:57:50 +00:00
int X = dst_rect . left ;
int Y = dst_rect . top ;
int Width = dst_rect . right - dst_rect . left ;
int Height = dst_rect . bottom - dst_rect . top ;
2010-09-30 15:24:34 +00:00
// Sanity check
2010-03-14 18:57:50 +00:00
if ( X < 0 ) X = 0 ;
if ( Y < 0 ) Y = 0 ;
if ( X > s_backbuffer_width ) X = s_backbuffer_width ;
if ( Y > s_backbuffer_height ) Y = s_backbuffer_height ;
if ( Width < 0 ) Width = 0 ;
if ( Height < 0 ) Height = 0 ;
if ( Width > ( s_backbuffer_width - X ) ) Width = s_backbuffer_width - X ;
if ( Height > ( s_backbuffer_height - Y ) ) Height = s_backbuffer_height - Y ;
2010-09-30 15:24:34 +00:00
2010-03-14 18:57:50 +00:00
vp . X = X ;
vp . Y = Y ;
vp . Width = Width ;
vp . Height = Height ;
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
D3D : : dev - > SetViewport ( & vp ) ;
D3D : : ChangeSamplerState ( 0 , D3DSAMP_MINFILTER , D3DTEXF_LINEAR ) ;
D3D : : ChangeSamplerState ( 0 , D3DSAMP_MAGFILTER , D3DTEXF_LINEAR ) ;
2010-09-30 15:24:34 +00:00
const XFBSource * xfbSource = NULL ;
2010-07-02 17:09:53 +00:00
if ( g_ActiveConfig . bUseXFB )
2010-03-14 18:57:50 +00:00
{
2010-07-02 17:09:53 +00:00
// draw each xfb source
2010-09-30 15:24:34 +00:00
// Render to the real buffer now.
2010-07-02 17:09:53 +00:00
for ( u32 i = 0 ; i < xfbCount ; + + i )
2010-03-14 18:57:50 +00:00
{
2010-09-28 02:15:02 +00:00
xfbSource = xfbSourceList [ i ] ;
2010-09-30 15:24:34 +00:00
2010-07-02 17:09:53 +00:00
MathUtil : : Rectangle < float > sourceRc ;
2010-05-24 14:20:19 +00:00
2010-07-02 17:09:53 +00:00
sourceRc . left = 0 ;
sourceRc . top = 0 ;
sourceRc . right = xfbSource - > texWidth ;
2010-09-28 02:15:02 +00:00
sourceRc . bottom = xfbSource - > texHeight ;
2010-07-02 17:09:53 +00:00
MathUtil : : Rectangle < float > drawRc ;
2010-03-14 18:57:50 +00:00
2010-09-30 15:24:34 +00:00
if ( ! g_ActiveConfig . bUseRealXFB )
2010-03-14 18:57:50 +00:00
{
2010-07-02 17:09:53 +00:00
// use virtual xfb with offset
int xfbHeight = xfbSource - > srcHeight ;
int xfbWidth = xfbSource - > srcWidth ;
int hOffset = ( ( s32 ) xfbSource - > srcAddr - ( s32 ) xfbAddr ) / ( ( s32 ) fbWidth * 2 ) ;
2010-09-28 02:15:02 +00:00
drawRc . bottom = 1.0f - ( 2.0f * ( hOffset ) / ( float ) fbHeight ) ;
drawRc . top = 1.0f - ( 2.0f * ( hOffset + xfbHeight ) / ( float ) fbHeight ) ;
2010-07-02 17:09:53 +00:00
drawRc . left = - ( xfbWidth / ( float ) fbWidth ) ;
drawRc . right = ( xfbWidth / ( float ) fbWidth ) ;
2010-09-30 15:24:34 +00:00
// The following code disables auto stretch. Kept for reference.
// scale draw area for a 1 to 1 pixel mapping with the draw target
//float vScale = (float)fbHeight / (float)dst_rect.GetHeight();
//float hScale = (float)fbWidth / (float)dst_rect.GetWidth();
//drawRc.top *= vScale;
//drawRc.bottom *= vScale;
//drawRc.left *= hScale;
//drawRc.right *= hScale;
2010-07-02 17:09:53 +00:00
}
else
{
drawRc . top = - 1 ;
drawRc . bottom = 1 ;
drawRc . left = - 1 ;
drawRc . right = 1 ;
2010-03-14 18:57:50 +00:00
}
2010-07-02 17:09:53 +00:00
D3D : : drawShadedTexSubQuad ( xfbSource - > texture , & sourceRc , xfbSource - > texWidth , xfbSource - > texHeight , & drawRc , Width , Height , PixelShaderCache : : GetColorCopyProgram ( 0 ) , VertexShaderCache : : GetSimpleVertexShader ( 0 ) ) ;
}
}
else
{
2010-09-30 15:24:34 +00:00
TargetRectangle targetRc = ConvertEFBRectangle ( rc ) ;
2010-09-28 02:15:02 +00:00
LPDIRECT3DTEXTURE9 read_texture = g_framebufferManager . GetEFBColorTexture ( rc ) ;
2010-07-02 17:09:53 +00:00
D3D : : drawShadedTexQuad ( read_texture , targetRc . AsRECT ( ) , Renderer : : GetFullTargetWidth ( ) , Renderer : : GetFullTargetHeight ( ) , Width , Height , PixelShaderCache : : GetColorCopyProgram ( g_Config . iMultisampleMode ) , VertexShaderCache : : GetSimpleVertexShader ( g_Config . iMultisampleMode ) ) ;
2010-03-14 18:57:50 +00:00
}
D3D : : RefreshSamplerState ( 0 , D3DSAMP_MINFILTER ) ;
2010-07-06 13:14:51 +00:00
D3D : : RefreshSamplerState ( 0 , D3DSAMP_MAGFILTER ) ;
2010-09-30 15:24:34 +00:00
2010-09-23 02:17:48 +00:00
if ( g_ActiveConfig . bAnaglyphStereo )
{
DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE ;
D3D : : SetRenderState ( D3DRS_COLORWRITEENABLE , color_mask ) ;
}
2010-09-30 15:24:34 +00:00
2010-03-14 18:57:50 +00:00
vp . X = 0 ;
vp . Y = 0 ;
vp . Width = s_backbuffer_width ;
vp . Height = s_backbuffer_height ;
vp . MinZ = 0.0f ;
vp . MaxZ = 1.0f ;
D3D : : dev - > SetViewport ( & vp ) ;
2010-09-30 15:24:34 +00:00
// Save screenshot
2010-09-28 02:15:02 +00:00
if ( s_bScreenshot )
2010-03-14 18:57:50 +00:00
{
s_criticalScreenshot . Enter ( ) ;
2010-07-12 19:30:25 +00:00
HRESULT hr = D3D : : dev - > GetRenderTargetData ( D3D : : GetBackBufferSurface ( ) , ScreenShootMEMSurface ) ;
2010-07-09 20:56:16 +00:00
if ( FAILED ( hr ) )
2010-05-29 10:09:24 +00:00
{
2010-07-09 20:56:16 +00:00
PanicAlert ( " Error dumping surface data. " ) ;
}
2010-07-17 11:42:28 +00:00
hr = PD3DXSaveSurfaceToFileA ( s_sScreenshotName , D3DXIFF_PNG , ScreenShootMEMSurface , NULL , dst_rect . AsRECT ( ) ) ;
2010-07-09 20:56:16 +00:00
if ( FAILED ( hr ) )
{
PanicAlert ( " Error saving screen. " ) ;
2010-05-29 10:09:24 +00:00
}
2010-03-14 18:57:50 +00:00
s_bScreenshot = false ;
s_criticalScreenshot . Leave ( ) ;
}
2010-07-06 13:14:51 +00:00
if ( g_ActiveConfig . bDumpFrames )
2010-03-14 18:57:50 +00:00
{
2010-07-09 20:56:16 +00:00
HRESULT hr = D3D : : dev - > GetRenderTargetData ( D3D : : GetBackBufferSurface ( ) , ScreenShootMEMSurface ) ;
2010-09-28 02:15:02 +00:00
if ( ! s_bLastFrameDumped )
2010-03-14 18:57:50 +00:00
{
2010-07-09 20:56:16 +00:00
s_recordWidth = dst_rect . GetWidth ( ) ;
s_recordHeight = dst_rect . GetHeight ( ) ;
2010-09-28 02:15:02 +00:00
s_bAVIDumping = AVIDump : : Start ( EmuWindow : : GetParentWnd ( ) , s_recordWidth , s_recordHeight ) ;
if ( ! s_bAVIDumping )
2010-03-14 18:57:50 +00:00
{
PanicAlert ( " Error dumping frames to AVI. " ) ;
2010-07-06 13:14:51 +00:00
}
else
2010-03-14 18:57:50 +00:00
{
char msg [ 255 ] ;
2010-06-13 19:41:07 +00:00
sprintf_s ( msg , 255 , " Dumping Frames to \" %sframedump0.avi \" (%dx%d RGB24) " , File : : GetUserPath ( D_DUMPFRAMES_IDX ) , s_recordWidth , s_recordHeight ) ;
2010-03-14 18:57:50 +00:00
OSD : : AddMessage ( msg , 2000 ) ;
}
}
2010-09-28 02:15:02 +00:00
if ( s_bAVIDumping )
2010-03-14 18:57:50 +00:00
{
D3DLOCKED_RECT rect ;
2010-07-09 20:56:16 +00:00
if ( SUCCEEDED ( ScreenShootMEMSurface - > LockRect ( & rect , dst_rect . AsRECT ( ) , D3DLOCK_NO_DIRTY_UPDATE | D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY ) ) )
2010-03-14 18:57:50 +00:00
{
2010-07-06 13:14:51 +00:00
char * data = ( char * ) malloc ( 3 * s_recordWidth * s_recordHeight ) ;
formatBufferDump ( ( const char * ) rect . pBits , data , s_recordWidth , s_recordHeight , rect . Pitch ) ;
2010-03-14 18:57:50 +00:00
AVIDump : : AddFrame ( data ) ;
free ( data ) ;
ScreenShootMEMSurface - > UnlockRect ( ) ;
}
}
2010-09-28 02:15:02 +00:00
s_bLastFrameDumped = true ;
2010-07-06 13:14:51 +00:00
}
else
2010-03-14 18:57:50 +00:00
{
2010-09-28 02:15:02 +00:00
if ( s_bLastFrameDumped & & s_bAVIDumping )
2010-03-14 18:57:50 +00:00
{
AVIDump : : Stop ( ) ;
2010-09-28 02:15:02 +00:00
s_bAVIDumping = false ;
OSD : : AddMessage ( " Stop dumping frames to AVI " , 2000 ) ;
2010-03-14 18:57:50 +00:00
}
2010-09-28 02:15:02 +00:00
s_bLastFrameDumped = false ;
2010-03-14 18:57:50 +00:00
}
// Finish up the current frame, print some stats
if ( g_ActiveConfig . bShowFPS )
{
char fps [ 20 ] ;
StringCchPrintfA ( fps , 20 , " FPS: %d \n " , s_fps ) ;
2010-07-06 13:14:51 +00:00
D3D : : font . DrawTextScaled ( 0 , 30 , 20 , 20 , 0.0f , 0xFF00FFFF , fps , false ) ;
2010-03-14 18:57:50 +00:00
}
Renderer : : DrawDebugText ( ) ;
if ( g_ActiveConfig . bOverlayStats )
{
Statistics : : ToString ( st ) ;
2010-07-06 13:14:51 +00:00
D3D : : font . DrawTextScaled ( 0 , 30 , 20 , 20 , 0.0f , 0xFF00FFFF , st , false ) ;
2010-03-14 18:57:50 +00:00
}
else if ( g_ActiveConfig . bOverlayProjStats )
{
Statistics : : ToStringProj ( st ) ;
2010-07-06 13:14:51 +00:00
D3D : : font . DrawTextScaled ( 0 , 30 , 20 , 20 , 0.0f , 0xFF00FFFF , st , false ) ;
2010-03-14 18:57:50 +00:00
}
OSD : : DrawMessages ( ) ;
D3D : : EndFrame ( ) ;
2009-09-20 03:29:43 +00:00
frameCount + + ;
2010-08-29 23:08:56 +00:00
DLCache : : ProgressiveCleanup ( ) ;
2009-09-20 03:29:43 +00:00
TextureCache : : Cleanup ( ) ;
2010-09-28 02:15:02 +00:00
// Enable any configuration changes
2010-07-06 13:14:51 +00:00
UpdateActiveConfig ( ) ;
2010-03-14 18:57:50 +00:00
WindowResized = false ;
2009-09-20 03:29:43 +00:00
CheckForResize ( ) ;
2010-09-28 02:15:02 +00:00
2010-03-14 18:57:50 +00:00
bool xfbchanged = false ;
2010-09-28 02:15:02 +00:00
2010-07-06 13:14:51 +00:00
if ( s_XFB_width ! = fbWidth | | s_XFB_height ! = fbHeight )
2010-03-14 18:57:50 +00:00
{
xfbchanged = true ;
s_XFB_width = fbWidth ;
s_XFB_height = fbHeight ;
2010-07-06 13:14:51 +00:00
if ( s_XFB_width < 1 ) s_XFB_width = MAX_XFB_WIDTH ;
if ( s_XFB_width > MAX_XFB_WIDTH ) s_XFB_width = MAX_XFB_WIDTH ;
if ( s_XFB_height < 1 ) s_XFB_height = MAX_XFB_HEIGHT ;
if ( s_XFB_height > MAX_XFB_HEIGHT ) s_XFB_height = MAX_XFB_HEIGHT ;
2010-03-14 18:57:50 +00:00
}
2009-09-20 03:29:43 +00:00
2010-02-05 21:55:02 +00:00
u32 newAA = g_ActiveConfig . iMultisampleMode ;
2010-09-30 15:24:34 +00:00
if ( xfbchanged | | WindowResized | | s_LastEFBScale ! = g_ActiveConfig . iEFBScale )
2010-07-06 13:14:51 +00:00
{
2010-02-03 22:19:00 +00:00
s_LastAA = newAA ;
2010-03-14 18:57:50 +00:00
ComputeDrawRectangle ( s_backbuffer_width , s_backbuffer_height , false , & dst_rect ) ;
if ( g_ActiveConfig . bUseRealXFB )
{
2010-09-30 15:24:34 +00:00
xScale = 1.0f ;
yScale = 1.0f ;
2010-03-14 18:57:50 +00:00
}
else
{
xScale = ( float ) ( dst_rect . right - dst_rect . left ) / ( float ) s_XFB_width ;
yScale = ( float ) ( dst_rect . bottom - dst_rect . top ) / ( float ) s_XFB_height ;
2010-05-19 03:15:36 +00:00
}
2010-03-14 18:57:50 +00:00
2010-07-02 17:09:53 +00:00
float SupersampleCoeficient = s_LastAA + 1 ;
2010-09-30 15:24:34 +00:00
s_LastEFBScale = g_ActiveConfig . iEFBScale ;
2010-06-09 15:33:01 +00:00
switch ( s_LastEFBScale )
{
2010-07-06 13:14:51 +00:00
case 0 :
2010-06-09 15:33:01 +00:00
EFBxScale = xScale ;
EFByScale = yScale ;
break ;
2010-07-06 13:14:51 +00:00
case 1 :
2010-06-09 15:33:01 +00:00
EFBxScale = ceilf ( xScale ) ;
EFByScale = ceilf ( yScale ) ;
break ;
default :
EFBxScale = g_ActiveConfig . iEFBScale - 1 ;
EFByScale = EFBxScale ;
break ;
} ;
EFBxScale * = SupersampleCoeficient ;
EFByScale * = SupersampleCoeficient ;
2010-09-30 15:24:34 +00:00
2010-06-05 00:01:18 +00:00
s_target_width = EFB_WIDTH * EFBxScale ;
s_target_height = EFB_HEIGHT * EFByScale ;
2010-09-30 15:24:34 +00:00
s_Fulltarget_width = s_target_width ;
s_Fulltarget_height = s_target_height ;
2010-02-03 22:19:00 +00:00
D3D : : dev - > SetRenderTarget ( 0 , D3D : : GetBackBufferSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( D3D : : GetBackBufferDepthSurface ( ) ) ;
2010-07-06 13:14:51 +00:00
if ( WindowResized )
2010-03-22 00:21:39 +00:00
{
SetupDeviceObjects ( ) ;
}
else
{
2010-09-28 02:15:02 +00:00
g_framebufferManager . Destroy ( ) ;
g_framebufferManager . Create ( ) ;
2010-03-22 00:21:39 +00:00
}
2010-09-28 02:15:02 +00:00
D3D : : dev - > SetRenderTarget ( 0 , g_framebufferManager . GetEFBColorRTSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( g_framebufferManager . GetEFBDepthRTSurface ( ) ) ;
2010-02-03 22:19:00 +00:00
}
2010-09-28 02:15:02 +00:00
// Place messages on the picture, then copy it to the screen
2009-11-28 05:59:46 +00:00
// ---------------------------------------------------------------------
// Count FPS.
// -------------
2010-08-01 14:43:07 +00:00
static int fpscount = 0 ;
static unsigned long lasttime = 0 ;
if ( Common : : Timer : : GetTimeMs ( ) - lasttime > = 1000 )
2010-02-25 06:12:35 +00:00
{
lasttime = Common : : Timer : : GetTimeMs ( ) ;
2010-08-01 14:43:07 +00:00
s_fps = fpscount ;
fpscount = 0 ;
2010-02-25 06:12:35 +00:00
}
2010-08-01 14:43:07 +00:00
if ( XFBWrited )
+ + fpscount ;
2009-09-20 03:29:43 +00:00
// Begin new frame
// Set default viewport and scissor, for the clear to work correctly
2010-09-28 02:15:02 +00:00
// New frame
2009-09-20 03:29:43 +00:00
stats . ResetFrame ( ) ;
// Flip/present backbuffer to frontbuffer here
D3D : : Present ( ) ;
2010-03-14 18:57:50 +00:00
D3D : : BeginFrame ( ) ;
2010-09-30 15:24:34 +00:00
RestoreAPIState ( ) ;
2010-09-28 02:15:02 +00:00
D3D : : dev - > SetRenderTarget ( 0 , g_framebufferManager . GetEFBColorRTSurface ( ) ) ;
D3D : : dev - > SetDepthStencilSurface ( g_framebufferManager . GetEFBDepthRTSurface ( ) ) ;
2010-03-14 18:57:50 +00:00
UpdateViewport ( ) ;
VertexShaderManager : : SetViewportChanged ( ) ;
2010-09-28 02:15:02 +00:00
// For testing zbuffer targets.
// Renderer::SetZBufferRender();
// SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_FakeZTarget,
// GetTargetWidth(), GetTargetHeight());
2010-06-24 15:58:06 +00:00
g_VideoInitialize . pCopiedToXFB ( XFBWrited | | g_ActiveConfig . bUseRealXFB ) ;
2010-03-14 18:57:50 +00:00
XFBWrited = false ;
2009-09-20 03:29:43 +00:00
}
2009-11-08 20:35:11 +00:00
2010-09-28 02:15:02 +00:00
// ALWAYS call RestoreAPIState for each ResetAPIState call you're doing
2009-11-08 20:35:11 +00:00
void Renderer : : ResetAPIState ( )
{
2010-01-15 22:07:53 +00:00
D3D : : SetRenderState ( D3DRS_SCISSORTESTENABLE , FALSE ) ;
2010-06-08 02:56:00 +00:00
D3D : : SetRenderState ( D3DRS_CULLMODE , D3DCULL_NONE ) ;
2010-02-25 06:12:35 +00:00
D3D : : SetRenderState ( D3DRS_ALPHABLENDENABLE , FALSE ) ;
D3D : : SetRenderState ( D3DRS_ZENABLE , FALSE ) ;
2010-06-08 02:56:00 +00:00
D3D : : SetRenderState ( D3DRS_ZWRITEENABLE , FALSE ) ;
2010-07-06 13:14:51 +00:00
DWORD color_mask = D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE ;
2010-01-15 22:07:53 +00:00
D3D : : SetRenderState ( D3DRS_COLORWRITEENABLE , color_mask ) ;
2009-11-08 20:35:11 +00:00
}
void Renderer : : RestoreAPIState ( )
{
// Gets us back into a more game-like state.
2010-01-15 22:07:53 +00:00
D3D : : SetRenderState ( D3DRS_SCISSORTESTENABLE , TRUE ) ;
ok big changes here:
in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-15 15:52:08 +00:00
UpdateViewport ( ) ;
2010-01-15 22:07:53 +00:00
SetScissorRect ( ) ;
2010-07-06 13:14:51 +00:00
if ( bpmem . zmode . testenable )
D3D : : SetRenderState ( D3DRS_ZENABLE , TRUE ) ;
if ( bpmem . zmode . updateenable )
D3D : : SetRenderState ( D3DRS_ZWRITEENABLE , TRUE ) ;
2010-02-25 06:12:35 +00:00
SetColorMask ( ) ;
2010-01-15 22:07:53 +00:00
SetLogicOpMode ( ) ;
2009-11-08 20:35:11 +00:00
}
2009-11-23 14:08:08 +00:00
void Renderer : : SetGenerationMode ( )
{
2010-02-25 06:12:35 +00:00
D3D : : SetRenderState ( D3DRS_CULLMODE , d3dCullModes [ bpmem . genMode . cullmode ] ) ;
2009-11-23 14:08:08 +00:00
}
void Renderer : : SetDepthMode ( )
{
if ( bpmem . zmode . testenable )
{
D3D : : SetRenderState ( D3DRS_ZENABLE , TRUE ) ;
D3D : : SetRenderState ( D3DRS_ZWRITEENABLE , bpmem . zmode . updateenable ) ;
2010-02-25 06:12:35 +00:00
D3D : : SetRenderState ( D3DRS_ZFUNC , d3dCmpFuncs [ bpmem . zmode . func ] ) ;
2009-11-23 14:08:08 +00:00
}
else
{
2010-09-28 02:15:02 +00:00
// if the test is disabled write is disabled too
2009-11-23 14:08:08 +00:00
D3D : : SetRenderState ( D3DRS_ZENABLE , FALSE ) ;
2010-02-25 06:12:35 +00:00
D3D : : SetRenderState ( D3DRS_ZWRITEENABLE , FALSE ) ; // ??
}
2009-11-23 14:08:08 +00:00
}
2009-11-27 19:42:27 +00:00
void Renderer : : SetLogicOpMode ( )
{
2010-07-06 13:14:51 +00:00
if ( bpmem . blendmode . logicopenable & & bpmem . blendmode . logicmode ! = 3 )
2009-12-07 18:48:31 +00:00
{
2010-06-24 15:58:06 +00:00
D3D : : SetRenderState ( D3DRS_ALPHABLENDENABLE , true ) ;
2010-06-05 01:38:22 +00:00
D3D : : SetRenderState ( D3DRS_BLENDOP , d3dLogicOpop [ bpmem . blendmode . logicmode ] ) ;
2009-12-07 18:48:31 +00:00
D3D : : SetRenderState ( D3DRS_SRCBLEND , d3dLogicOpSrcFactors [ bpmem . blendmode . logicmode ] ) ;
D3D : : SetRenderState ( D3DRS_DESTBLEND , d3dLogicOpDestFactors [ bpmem . blendmode . logicmode ] ) ;
}
else
{
SetBlendMode ( true ) ;
}
2009-11-27 19:42:27 +00:00
}
void Renderer : : SetDitherMode ( )
{
2010-07-06 13:14:51 +00:00
D3D : : SetRenderState ( D3DRS_DITHERENABLE , bpmem . blendmode . dither ) ;
2009-11-27 19:42:27 +00:00
}
void Renderer : : SetLineWidth ( )
{
// We can't change line width in D3D unless we use ID3DXLine
2010-01-25 01:10:46 +00:00
float fratio = xfregs . rawViewport [ 0 ] ! = 0 ? Renderer : : GetTargetScaleX ( ) : 1.0f ;
float psize = bpmem . lineptwidth . linesize * fratio / 6.0f ;
2009-11-27 19:42:27 +00:00
D3D : : SetRenderState ( D3DRS_POINTSIZE , * ( ( DWORD * ) & psize ) ) ;
}
2010-01-12 23:40:30 +00:00
void Renderer : : SetSamplerState ( int stage , int texindex )
2009-11-27 19:42:27 +00:00
{
2010-07-06 13:14:51 +00:00
const FourTexUnits & tex = bpmem . tex [ texindex ] ;
2009-11-27 19:42:27 +00:00
const TexMode0 & tm0 = tex . texMode0 [ stage ] ;
2010-04-14 13:57:16 +00:00
const TexMode1 & tm1 = tex . texMode1 [ stage ] ;
2009-11-27 19:42:27 +00:00
D3DTEXTUREFILTERTYPE min , mag , mip ;
if ( g_ActiveConfig . bForceFiltering )
{
min = mag = mip = D3DTEXF_LINEAR ;
}
else
{
min = ( tm0 . min_filter & 4 ) ? D3DTEXF_LINEAR : D3DTEXF_POINT ;
mag = tm0 . mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT ;
2010-07-06 13:14:51 +00:00
mip = ( tm0 . min_filter = = 8 ) ? D3DTEXF_NONE : d3dMipFilters [ tm0 . min_filter & 3 ] ;
if ( ( tm0 . min_filter & 3 ) & & ( tm0 . min_filter ! = 8 ) & & ( ( tm1 . max_lod > > 4 ) = = 0 ) )
mip = D3DTEXF_NONE ;
2009-11-27 19:42:27 +00:00
}
if ( texindex )
2010-07-06 13:14:51 +00:00
stage + = 4 ;
2009-11-27 19:42:27 +00:00
2010-07-06 13:14:51 +00:00
if ( mag = = D3DTEXF_LINEAR & & min = = D3DTEXF_LINEAR & & g_ActiveConfig . iMaxAnisotropy > 1 )
2009-11-27 19:42:27 +00:00
{
min = D3DTEXF_ANISOTROPIC ;
}
D3D : : SetSamplerState ( stage , D3DSAMP_MINFILTER , min ) ;
D3D : : SetSamplerState ( stage , D3DSAMP_MAGFILTER , mag ) ;
D3D : : SetSamplerState ( stage , D3DSAMP_MIPFILTER , mip ) ;
D3D : : SetSamplerState ( stage , D3DSAMP_ADDRESSU , d3dClamps [ tm0 . wrap_s ] ) ;
D3D : : SetSamplerState ( stage , D3DSAMP_ADDRESSV , d3dClamps [ tm0 . wrap_t ] ) ;
2010-07-02 17:09:53 +00:00
//float SuperSampleCoeficient = (s_LastAA < 3)? s_LastAA + 1 : s_LastAA - 1;// uncoment this changes to conserve detail when incresing ssaa level
float lodbias = ( tm0 . lod_bias / 32.0f ) ; // + (s_LastAA)?(log(SuperSampleCoeficient) / log(2.0f)):0;
2010-07-06 13:14:51 +00:00
D3D : : SetSamplerState ( stage , D3DSAMP_MIPMAPLODBIAS , * ( DWORD * ) & lodbias ) ;
D3D : : SetSamplerState ( stage , D3DSAMP_MAXMIPLEVEL , tm1 . min_lod > > 4 ) ;
2009-11-27 19:42:27 +00:00
}
void Renderer : : SetInterlacingMode ( )
{
// TODO
}
2010-01-27 22:07:59 +00:00
// Save screenshot
void Renderer : : SetScreenshot ( const char * filename )
{
s_criticalScreenshot . Enter ( ) ;
2010-07-06 13:14:51 +00:00
strcpy_s ( s_sScreenshotName , filename ) ;
2010-01-27 22:07:59 +00:00
s_bScreenshot = true ;
s_criticalScreenshot . Leave ( ) ;
}