2009-02-09 21:15:56 +00:00
/*
* Copyright ( C ) 2007 - 2009 Gabest
* http : //www.gabest.org
*
* 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 ; either version 2 , or ( at your option )
* any later version .
*
* 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 for more details .
*
* You should have received a copy of the GNU General Public License
* along with GNU Make ; see the file COPYING . If not , write to
* the Free Software Foundation , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
* http : //www.gnu.org/copyleft/gpl.html
*
*/
# pragma once
# include "GSWnd.h"
# include "GSState.h"
# include "GSVertexList.h"
# include "GSSettingsDlg.h"
# include "GSCapture.h"
struct GSRendererSettings
{
int m_interlace ;
int m_aspectratio ;
int m_filter ;
bool m_vsync ;
bool m_nativeres ;
2009-03-09 01:42:56 +00:00
bool m_aa1 ;
2009-03-24 09:11:03 +00:00
bool m_blur ;
2009-02-09 21:15:56 +00:00
} ;
class GSRendererBase : public GSState , protected GSRendererSettings
{
protected :
bool m_osd ;
void ProcessWindowMessages ( )
{
MSG msg ;
memset ( & msg , 0 , sizeof ( msg ) ) ;
while ( msg . message ! = WM_QUIT & & PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) )
{
if ( OnMessage ( msg ) )
{
continue ;
}
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
}
virtual bool OnMessage ( const MSG & msg )
{
if ( msg . message = = WM_KEYDOWN )
{
int step = ( : : GetAsyncKeyState ( VK_SHIFT ) & 0x8000 ) ? - 1 : 1 ;
2009-04-12 19:46:42 +00:00
switch ( msg . wParam )
2009-02-09 21:15:56 +00:00
{
2009-04-12 19:46:42 +00:00
case VK_F5 :
2009-02-09 21:15:56 +00:00
m_interlace = ( m_interlace + 7 + step ) % 7 ;
return true ;
2009-04-12 19:46:42 +00:00
case VK_F6 :
2009-02-09 21:15:56 +00:00
m_aspectratio = ( m_aspectratio + 3 + step ) % 3 ;
return true ;
2009-04-12 19:46:42 +00:00
case VK_F7 :
2009-02-09 21:15:56 +00:00
m_wnd . SetWindowText ( _T ( " PCSX2 " ) ) ;
m_osd = ! m_osd ;
return true ;
2009-04-12 19:46:42 +00:00
case VK_DELETE :
2009-03-09 01:42:56 +00:00
m_aa1 = ! m_aa1 ;
return true ;
2009-04-12 19:46:42 +00:00
case VK_END :
2009-03-24 09:11:03 +00:00
m_blur = ! m_blur ;
return true ;
2009-04-12 19:46:42 +00:00
}
2009-02-09 21:15:56 +00:00
}
return false ;
}
public :
GSWnd m_wnd ;
public :
2009-05-14 16:41:52 +00:00
GSRendererBase ( uint8 * base , bool mt , void ( * irq ) ( ) , const GSRendererSettings & rs )
2009-04-17 01:06:27 +00:00
: GSState ( base , mt , irq )
2009-02-09 21:15:56 +00:00
, m_osd ( true )
{
m_interlace = rs . m_interlace ;
m_aspectratio = rs . m_aspectratio ;
m_filter = rs . m_filter ;
m_vsync = rs . m_vsync ;
m_nativeres = rs . m_nativeres ;
2009-03-09 01:42:56 +00:00
m_aa1 = rs . m_aa1 ;
2009-03-24 09:11:03 +00:00
m_blur = rs . m_blur ;
2009-02-09 21:15:56 +00:00
} ;
2009-05-11 08:18:00 +00:00
virtual bool Create ( const string & title ) = 0 ;
2009-02-09 21:15:56 +00:00
virtual void VSync ( int field ) = 0 ;
2009-05-11 08:18:00 +00:00
virtual bool MakeSnapshot ( const string & path ) = 0 ;
2009-02-09 21:15:56 +00:00
} ;
template < class Device > class GSRenderer : public GSRendererBase
{
protected :
typedef typename Device : : Texture Texture ;
virtual void ResetDevice ( ) { }
virtual bool GetOutput ( int i , Texture & t ) = 0 ;
2009-03-22 13:10:31 +00:00
bool Merge ( int field )
2009-02-09 21:15:56 +00:00
{
2009-03-20 09:10:37 +00:00
bool en [ 2 ] ;
2009-05-14 16:41:52 +00:00
GSVector4i fr [ 2 ] ;
GSVector4i dr [ 2 ] ;
2009-03-20 09:10:37 +00:00
2009-02-09 21:15:56 +00:00
int baseline = INT_MAX ;
for ( int i = 0 ; i < 2 ; i + + )
{
2009-03-20 09:10:37 +00:00
en [ i ] = IsEnabled ( i ) ;
if ( en [ i ] )
2009-02-09 21:15:56 +00:00
{
2009-03-20 09:10:37 +00:00
fr [ i ] = GetFrameRect ( i ) ;
dr [ i ] = GetDisplayRect ( i ) ;
baseline = min ( dr [ i ] . top , baseline ) ;
2009-03-22 13:10:31 +00:00
// printf("[%d]: %d %d %d %d, %d %d %d %d\n", i, fr[i], dr[i]);
2009-03-20 09:10:37 +00:00
}
}
2009-03-24 09:11:03 +00:00
if ( ! en [ 0 ] & & ! en [ 1 ] )
{
return false ;
}
2009-03-20 09:10:37 +00:00
// try to avoid fullscreen blur, could be nice on tv but on a monitor it's like double vision, hurts my eyes (persona 4, guitar hero)
//
// NOTE: probably the technique explained in graphtip.pdf (Antialiasing by Supersampling / 4. Reading Odd/Even Scan Lines Separately with the PCRTC then Blending)
2009-03-31 03:19:21 +00:00
bool samesrc =
en [ 0 ] & & en [ 1 ] & &
m_regs - > DISP [ 0 ] . DISPFB . FBP = = m_regs - > DISP [ 1 ] . DISPFB . FBP & &
m_regs - > DISP [ 0 ] . DISPFB . FBW = = m_regs - > DISP [ 1 ] . DISPFB . FBW & &
m_regs - > DISP [ 0 ] . DISPFB . PSM = = m_regs - > DISP [ 1 ] . DISPFB . PSM ;
2009-03-24 09:11:03 +00:00
bool blurdetected = false ;
2009-03-31 03:19:21 +00:00
if ( samesrc & & m_regs - > PMODE . SLBG = = 0 & & m_regs - > PMODE . MMOD = = 1 & & m_regs - > PMODE . ALP = = 0x80 )
2009-03-20 09:10:37 +00:00
{
2009-05-15 21:07:58 +00:00
if ( fr [ 0 ] . eq ( fr [ 1 ] + GSVector4i ( 0 , - 1 , 0 , 0 ) ) & & dr [ 0 ] . eq ( dr [ 1 ] + GSVector4i ( 0 , 0 , 0 , 1 ) )
| | fr [ 1 ] . eq ( fr [ 0 ] + GSVector4i ( 0 , - 1 , 0 , 0 ) ) & & dr [ 1 ] . eq ( dr [ 0 ] + GSVector4i ( 0 , 0 , 0 , 1 ) ) )
2009-03-20 09:10:37 +00:00
{
2009-03-24 09:11:03 +00:00
// persona 4:
//
// fr[0] = 0 0 640 448
// fr[1] = 0 1 640 448
// dr[0] = 159 50 779 498
// dr[1] = 159 50 779 497
//
// second image shifted up by 1 pixel and blended over itself
//
// god of war:
//
// fr[0] = 0 1 512 448
// fr[1] = 0 0 512 448
// dr[0] = 127 50 639 497
// dr[1] = 127 50 639 498
//
// same just the first image shifted
int top = min ( fr [ 0 ] . top , fr [ 1 ] . top ) ;
int bottom = max ( dr [ 0 ] . bottom , dr [ 1 ] . bottom ) ;
fr [ 0 ] . top = top ;
fr [ 1 ] . top = top ;
dr [ 0 ] . bottom = bottom ;
dr [ 1 ] . bottom = bottom ;
blurdetected = true ;
}
2009-05-14 16:41:52 +00:00
else if ( dr [ 0 ] . eq ( dr [ 1 ] ) & & ( fr [ 0 ] . eq ( fr [ 1 ] + GSVector4i ( 0 , 1 , 0 , 1 ) ) | | fr [ 1 ] . eq ( fr [ 0 ] + GSVector4i ( 0 , 1 , 0 , 1 ) ) ) )
2009-03-24 09:11:03 +00:00
{
// dq5:
//
// fr[0] = 0 1 512 445
// fr[1] = 0 0 512 444
// dr[0] = 127 50 639 494
// dr[1] = 127 50 639 494
int top = min ( fr [ 0 ] . top , fr [ 1 ] . top ) ;
int bottom = min ( fr [ 0 ] . bottom , fr [ 1 ] . bottom ) ;
fr [ 0 ] . top = fr [ 1 ] . top = top ;
fr [ 0 ] . bottom = fr [ 1 ] . bottom = bottom ;
blurdetected = true ;
2009-02-09 21:15:56 +00:00
}
}
2009-05-14 16:41:52 +00:00
GSVector2i fs ( 0 , 0 ) ;
GSVector2i ds ( 0 , 0 ) ;
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
Texture tex [ 2 ] ;
2009-03-24 09:11:03 +00:00
if ( samesrc & & fr [ 0 ] . bottom = = fr [ 1 ] . bottom )
{
GetOutput ( 0 , tex [ 0 ] ) ;
tex [ 1 ] = tex [ 0 ] ; // saves one texture fetch
}
else
{
if ( en [ 0 ] ) GetOutput ( 0 , tex [ 0 ] ) ;
if ( en [ 1 ] ) GetOutput ( 1 , tex [ 1 ] ) ;
}
2009-03-20 09:10:37 +00:00
GSVector4 src [ 2 ] ;
GSVector4 dst [ 2 ] ;
2009-02-09 21:15:56 +00:00
for ( int i = 0 ; i < 2 ; i + + )
{
2009-03-24 09:11:03 +00:00
if ( ! en [ i ] | | ! tex [ i ] ) continue ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
GSVector4i r = fr [ i ] ;
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
// overscan hack
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
if ( dr [ i ] . height ( ) > 512 ) // hmm
2009-03-20 09:10:37 +00:00
{
2009-05-14 16:41:52 +00:00
int y = GetDeviceRect ( i ) . height ( ) ;
2009-03-31 03:19:21 +00:00
if ( m_regs - > SMODE2 . INT & & m_regs - > SMODE2 . FFMD ) y / = 2 ;
2009-03-20 09:10:37 +00:00
r . bottom = r . top + y ;
}
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
//
2009-02-09 21:15:56 +00:00
2009-03-24 09:11:03 +00:00
if ( m_blur & & blurdetected & & i = = 1 )
{
src [ i ] . x = tex [ i ] . m_scale . x * r . left / tex [ i ] . GetWidth ( ) ;
src [ i ] . y = ( tex [ i ] . m_scale . y * r . top + 1 ) / tex [ i ] . GetHeight ( ) ;
src [ i ] . z = tex [ i ] . m_scale . x * r . right / tex [ i ] . GetWidth ( ) ;
src [ i ] . w = ( tex [ i ] . m_scale . y * r . bottom + 1 ) / tex [ i ] . GetHeight ( ) ;
}
else
{
src [ i ] . x = tex [ i ] . m_scale . x * r . left / tex [ i ] . GetWidth ( ) ;
src [ i ] . y = tex [ i ] . m_scale . y * r . top / tex [ i ] . GetHeight ( ) ;
src [ i ] . z = tex [ i ] . m_scale . x * r . right / tex [ i ] . GetWidth ( ) ;
src [ i ] . w = tex [ i ] . m_scale . y * r . bottom / tex [ i ] . GetHeight ( ) ;
}
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
GSVector2 o ;
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
o . x = 0 ;
o . y = 0 ;
if ( dr [ i ] . top - baseline > = 4 ) // 2?
{
o . y = tex [ i ] . m_scale . y * ( dr [ i ] . top - baseline ) ;
2009-02-09 21:15:56 +00:00
}
2009-03-20 09:10:37 +00:00
2009-03-31 03:19:21 +00:00
if ( m_regs - > SMODE2 . INT & & m_regs - > SMODE2 . FFMD ) o . y / = 2 ;
2009-03-20 09:10:37 +00:00
dst [ i ] . x = o . x ;
dst [ i ] . y = o . y ;
2009-05-14 16:41:52 +00:00
dst [ i ] . z = o . x + tex [ i ] . m_scale . x * r . width ( ) ;
dst [ i ] . w = o . y + tex [ i ] . m_scale . y * r . height ( ) ;
2009-03-20 09:10:37 +00:00
2009-05-14 16:41:52 +00:00
fs . x = max ( fs . x , ( int ) ( dst [ i ] . z + 0.5f ) ) ;
fs . y = max ( fs . y , ( int ) ( dst [ i ] . w + 0.5f ) ) ;
2009-02-09 21:15:56 +00:00
}
2009-05-14 16:41:52 +00:00
ds = fs ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
if ( m_regs - > SMODE2 . INT & & m_regs - > SMODE2 . FFMD ) ds . y * = 2 ;
2009-02-09 21:15:56 +00:00
2009-03-31 03:19:21 +00:00
bool slbg = m_regs - > PMODE . SLBG ;
bool mmod = m_regs - > PMODE . MMOD ;
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
if ( tex [ 0 ] | | tex [ 1 ] )
2009-02-09 21:15:56 +00:00
{
GSVector4 c ;
2009-03-31 03:19:21 +00:00
c . r = ( float ) m_regs - > BGCOLOR . R / 255 ;
c . g = ( float ) m_regs - > BGCOLOR . G / 255 ;
c . b = ( float ) m_regs - > BGCOLOR . B / 255 ;
c . a = ( float ) m_regs - > PMODE . ALP / 255 ;
2009-02-09 21:15:56 +00:00
2009-03-20 09:10:37 +00:00
m_dev . Merge ( tex , src , dst , fs , slbg , mmod , c ) ;
2009-02-09 21:15:56 +00:00
2009-03-31 03:19:21 +00:00
if ( m_regs - > SMODE2 . INT & & m_interlace > 0 )
2009-02-09 21:15:56 +00:00
{
2009-03-22 13:10:31 +00:00
int field2 = 1 - ( ( m_interlace - 1 ) & 1 ) ;
2009-02-09 21:15:56 +00:00
int mode = ( m_interlace - 1 ) > > 1 ;
2009-03-22 13:10:31 +00:00
if ( ! m_dev . Interlace ( ds , field ^ field2 , mode , tex [ 1 ] . m_scale . y ) )
2009-02-09 21:15:56 +00:00
{
return false ;
}
}
}
return true ;
}
2009-03-22 13:10:31 +00:00
void DoSnapshot ( int field )
{
2009-05-11 08:18:00 +00:00
if ( ! m_snapshot . empty ( ) )
2009-03-22 13:10:31 +00:00
{
if ( ! m_dump & & ( : : GetAsyncKeyState ( VK_SHIFT ) & 0x8000 ) )
{
GSFreezeData fd ;
fd . size = 0 ;
fd . data = NULL ;
Freeze ( & fd , true ) ;
2009-05-14 16:41:52 +00:00
fd . data = new uint8 [ fd . size ] ;
2009-03-22 13:10:31 +00:00
Freeze ( & fd , false ) ;
2009-03-31 03:19:21 +00:00
m_dump . Open ( m_snapshot , m_crc , fd , m_regs ) ;
2009-03-22 13:10:31 +00:00
delete [ ] fd . data ;
}
2009-05-11 08:18:00 +00:00
m_dev . SaveCurrent ( m_snapshot + " .bmp " ) ;
2009-03-22 13:10:31 +00:00
2009-05-11 08:18:00 +00:00
m_snapshot . clear ( ) ;
2009-03-22 13:10:31 +00:00
}
else
{
if ( m_dump )
{
2009-03-31 03:19:21 +00:00
m_dump . VSync ( field , ! ( : : GetAsyncKeyState ( VK_CONTROL ) & 0x8000 ) , m_regs ) ;
2009-03-22 13:10:31 +00:00
}
}
}
2009-02-09 21:15:56 +00:00
void DoCapture ( )
{
if ( ! m_capture . IsCapturing ( ) )
{
return ;
}
2009-05-14 16:41:52 +00:00
GSVector2i size = m_capture . GetSize ( ) ;
2009-02-09 21:15:56 +00:00
Texture current ;
m_dev . GetCurrent ( current ) ;
Texture offscreen ;
2009-05-14 16:41:52 +00:00
if ( m_dev . CopyOffscreen ( current , GSVector4 ( 0 , 0 , 1 , 1 ) , offscreen , size . x , size . y ) )
2009-02-09 21:15:56 +00:00
{
2009-05-14 16:41:52 +00:00
uint8 * bits = NULL ;
2009-02-09 21:15:56 +00:00
int pitch = 0 ;
if ( offscreen . Map ( & bits , pitch ) )
{
m_capture . DeliverFrame ( bits , pitch , m_dev . IsCurrentRGBA ( ) ) ;
offscreen . Unmap ( ) ;
}
m_dev . Recycle ( offscreen ) ;
}
}
virtual bool OnMessage ( const MSG & msg )
{
if ( msg . message = = WM_KEYDOWN )
{
2009-04-12 19:46:42 +00:00
switch ( msg . wParam )
2009-02-09 21:15:56 +00:00
{
2009-04-12 19:46:42 +00:00
case VK_F12 :
if ( m_capture . IsCapturing ( ) ) m_capture . EndCapture ( ) ;
else m_capture . BeginCapture ( GetFPS ( ) ) ;
2009-02-09 21:15:56 +00:00
return true ;
}
}
return __super : : OnMessage ( msg ) ;
}
public :
Device m_dev ;
bool m_psrr ;
int s_n ;
bool s_dump ;
bool s_save ;
bool s_savez ;
2009-05-11 08:18:00 +00:00
string m_snapshot ;
2009-02-09 21:15:56 +00:00
GSCapture m_capture ;
public :
2009-05-14 16:41:52 +00:00
GSRenderer ( uint8 * base , bool mt , void ( * irq ) ( ) , const GSRendererSettings & rs , bool psrr )
2009-04-17 01:06:27 +00:00
: GSRendererBase ( base , mt , irq , rs )
2009-02-09 21:15:56 +00:00
, m_psrr ( psrr )
{
s_n = 0 ;
s_dump = ! ! AfxGetApp ( ) - > GetProfileInt ( _T ( " Debug " ) , _T ( " dump " ) , 0 ) ;
s_save = ! ! AfxGetApp ( ) - > GetProfileInt ( _T ( " Debug " ) , _T ( " save " ) , 0 ) ;
s_savez = ! ! AfxGetApp ( ) - > GetProfileInt ( _T ( " Debug " ) , _T ( " savez " ) , 0 ) ;
}
2009-05-11 08:18:00 +00:00
bool Create ( const string & title )
2009-02-09 21:15:56 +00:00
{
2009-05-11 08:18:00 +00:00
if ( ! m_wnd . Create ( title . c_str ( ) ) )
2009-02-09 21:15:56 +00:00
{
return false ;
}
if ( ! m_dev . Create ( m_wnd , m_vsync ) )
{
return false ;
}
Reset ( ) ;
return true ;
}
void VSync ( int field )
{
GSPerfMonAutoTimer pmat ( m_perfmon ) ;
Flush ( ) ;
m_perfmon . Put ( GSPerfMon : : Frame ) ;
ProcessWindowMessages ( ) ;
2009-03-22 13:10:31 +00:00
field = field ? 1 : 0 ;
2009-02-09 21:15:56 +00:00
2009-03-22 13:10:31 +00:00
if ( ! Merge ( field ) ) return ;
2009-02-09 21:15:56 +00:00
// osd
2009-05-15 11:11:26 +00:00
static uint64 s_frame = 0 ;
2009-05-11 08:18:00 +00:00
static string s_stats ;
2009-02-09 21:15:56 +00:00
if ( m_perfmon . GetFrame ( ) - s_frame > = 30 )
{
m_perfmon . Update ( ) ;
s_frame = m_perfmon . GetFrame ( ) ;
double fps = 1000.0f / m_perfmon . Get ( GSPerfMon : : Frame ) ;
2009-05-11 08:18:00 +00:00
2009-05-14 16:41:52 +00:00
string s = m_regs - > SMODE2 . INT ? ( string ( " Interlaced " ) + ( m_regs - > SMODE2 . FFMD ? " (frame) " : " (field) " ) ) : " Progressive " ;
GSVector4i r = GetDisplayRect ( ) ;
2009-02-09 21:15:56 +00:00
2009-05-11 08:18:00 +00:00
s_stats = format (
" %I64d | %d x %d | %.2f fps (%d%%) | %s - %s | %s | %d/%d/%d | %d%% CPU | %.2f | %.2f " ,
2009-05-14 16:41:52 +00:00
m_perfmon . GetFrame ( ) , r . width ( ) , r . height ( ) , fps , ( int ) ( 100.0 * fps / GetFPS ( ) ) ,
s . c_str ( ) ,
2009-02-09 21:15:56 +00:00
GSSettingsDlg : : g_interlace [ m_interlace ] . name ,
GSSettingsDlg : : g_aspectratio [ m_aspectratio ] . name ,
( int ) m_perfmon . Get ( GSPerfMon : : Quad ) ,
( int ) m_perfmon . Get ( GSPerfMon : : Prim ) ,
( int ) m_perfmon . Get ( GSPerfMon : : Draw ) ,
m_perfmon . CPU ( ) ,
m_perfmon . Get ( GSPerfMon : : Swizzle ) / 1024 ,
m_perfmon . Get ( GSPerfMon : : Unswizzle ) / 1024
) ;
double fillrate = m_perfmon . Get ( GSPerfMon : : Fillrate ) ;
if ( fillrate > 0 )
{
2009-05-11 08:18:00 +00:00
s_stats + = format ( " | %.2f mpps " , fps * fillrate / ( 1024 * 1024 ) ) ;
2009-02-09 21:15:56 +00:00
}
if ( m_capture . IsCapturing ( ) )
{
2009-05-11 08:18:00 +00:00
s_stats + = " | Recording... " ;
2009-02-09 21:15:56 +00:00
}
2009-05-11 08:18:00 +00:00
m_wnd . SetWindowText ( s_stats . c_str ( ) ) ;
2009-02-09 21:15:56 +00:00
}
if ( m_osd )
{
2009-05-11 08:18:00 +00:00
m_dev . Draw ( s_stats + " \n \n F5: interlace mode \n F6: aspect ratio \n F7: OSD " ) ;
2009-02-09 21:15:56 +00:00
}
if ( m_frameskip )
{
return ;
}
//
if ( m_dev . IsLost ( ) )
{
ResetDevice ( ) ;
}
//
2009-05-14 16:41:52 +00:00
GSVector4i r ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
m_wnd . GetClientRect ( r ) ;
2009-02-09 21:15:56 +00:00
2009-05-14 16:41:52 +00:00
m_dev . Present ( r . fit ( m_aspectratio ) ) ;
2009-02-09 21:15:56 +00:00
2009-03-22 13:10:31 +00:00
//
DoSnapshot ( field ) ;
2009-02-09 21:15:56 +00:00
DoCapture ( ) ;
}
2009-05-11 08:18:00 +00:00
bool MakeSnapshot ( const string & path )
2009-02-09 21:15:56 +00:00
{
2009-05-11 08:18:00 +00:00
if ( m_snapshot . empty ( ) )
2009-02-09 21:15:56 +00:00
{
2009-05-11 08:18:00 +00:00
m_snapshot = format ( " %s_%s " , path . c_str ( ) , CTime : : GetCurrentTime ( ) . Format ( _T ( " %Y%m%d%H%M%S " ) ) ) ;
2009-02-09 21:15:56 +00:00
}
2009-03-22 13:10:31 +00:00
return true ;
2009-02-09 21:15:56 +00:00
}
2009-05-14 16:41:52 +00:00
virtual void MinMaxUV ( int w , int h , GSVector4i & r ) { r = GSVector4i ( 0 , 0 , w , h ) ; }
2009-02-09 21:15:56 +00:00
virtual bool CanUpscale ( ) { return ! m_nativeres ; }
} ;
template < class Device , class Vertex > class GSRendererT : public GSRenderer < Device >
{
protected :
Vertex * m_vertices ;
int m_count ;
int m_maxcount ;
GSVertexList < Vertex > m_vl ;
void Reset ( )
{
m_count = 0 ;
m_vl . RemoveAll ( ) ;
__super : : Reset ( ) ;
}
void ResetPrim ( )
{
m_vl . RemoveAll ( ) ;
}
void FlushPrim ( )
{
if ( m_count > 0 )
{
/*
TRACE ( _T ( " [%d] Draw f %05x (%d) z %05x (%d %d %d %d) t %05x %05x (%d) \n " ) ,
( int ) m_perfmon . GetFrame ( ) ,
( int ) m_context - > FRAME . Block ( ) ,
( int ) m_context - > FRAME . PSM ,
( int ) m_context - > ZBUF . Block ( ) ,
( int ) m_context - > ZBUF . PSM ,
m_context - > TEST . ZTE ,
m_context - > TEST . ZTST ,
m_context - > ZBUF . ZMSK ,
PRIM - > TME ? ( int ) m_context - > TEX0 . TBP0 : 0xfffff ,
PRIM - > TME & & m_context - > TEX0 . PSM > PSM_PSMCT16S ? ( int ) m_context - > TEX0 . CBP : 0xfffff ,
PRIM - > TME ? ( int ) m_context - > TEX0 . PSM : 0xff ) ;
*/
if ( GSUtil : : EncodePSM ( m_context - > FRAME . PSM ) ! = 3 & & GSUtil : : EncodePSM ( m_context - > ZBUF . PSM ) ! = 3 )
{
// FIXME: berserk fpsm = 27 (8H)
Draw ( ) ;
}
m_count = 0 ;
}
}
void GrowVertexBuffer ( )
{
m_maxcount = max ( 10000 , m_maxcount * 3 / 2 ) ;
m_vertices = ( Vertex * ) _aligned_realloc ( m_vertices , sizeof ( Vertex ) * m_maxcount , 16 ) ;
m_maxcount - = 100 ;
}
2009-05-14 16:41:52 +00:00
template < uint32 prim > __forceinline Vertex * DrawingKick ( bool skip , int & count )
2009-02-09 21:15:56 +00:00
{
switch ( prim )
{
case GS_POINTLIST : count = 1 ; break ;
case GS_LINELIST : count = 2 ; break ;
case GS_LINESTRIP : count = 2 ; break ;
case GS_TRIANGLELIST : count = 3 ; break ;
case GS_TRIANGLESTRIP : count = 3 ; break ;
case GS_TRIANGLEFAN : count = 3 ; break ;
case GS_SPRITE : count = 2 ; break ;
case GS_INVALID : count = 1 ; break ;
default : __assume ( 0 ) ;
}
if ( m_vl . GetCount ( ) < count )
{
return NULL ;
}
if ( m_count > = m_maxcount )
{
GrowVertexBuffer ( ) ;
}
Vertex * v = & m_vertices [ m_count ] ;
switch ( prim )
{
case GS_POINTLIST :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . RemoveAll ( ) ;
break ;
case GS_LINELIST :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . RemoveAll ( ) ;
break ;
case GS_LINESTRIP :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . RemoveAt ( 0 , 1 ) ;
break ;
case GS_TRIANGLELIST :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . GetAt ( 2 , v [ 2 ] ) ;
m_vl . RemoveAll ( ) ;
break ;
case GS_TRIANGLESTRIP :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . GetAt ( 2 , v [ 2 ] ) ;
m_vl . RemoveAt ( 0 , 2 ) ;
break ;
case GS_TRIANGLEFAN :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . GetAt ( 2 , v [ 2 ] ) ;
m_vl . RemoveAt ( 1 , 1 ) ;
break ;
case GS_SPRITE :
m_vl . GetAt ( 0 , v [ 0 ] ) ;
m_vl . GetAt ( 1 , v [ 1 ] ) ;
m_vl . RemoveAll ( ) ;
break ;
case GS_INVALID :
ASSERT ( 0 ) ;
m_vl . RemoveAll ( ) ;
return NULL ;
default :
__assume ( 0 ) ;
}
return ! skip ? v : NULL ;
}
virtual void Draw ( ) = 0 ;
public :
2009-05-14 16:41:52 +00:00
GSRendererT ( uint8 * base , bool mt , void ( * irq ) ( ) , const GSRendererSettings & rs , bool psrr = true )
2009-04-17 01:06:27 +00:00
: GSRenderer < Device > ( base , mt , irq , rs , psrr )
2009-02-09 21:15:56 +00:00
, m_count ( 0 )
, m_maxcount ( 0 )
, m_vertices ( NULL )
{
}
~ GSRendererT ( )
{
if ( m_vertices ) _aligned_free ( m_vertices ) ;
}
} ;