2015-05-24 06:55:12 +02:00
// Copyright 2010 Dolphin Emulator Project
2015-05-18 01:08:10 +02:00
// Licensed under GPLv2+
2013-04-17 23:43:35 -04:00
// Refer to the license.txt file included.
2010-12-05 14:15:36 +00:00
2014-02-22 23:36:30 +01:00
#include <cstddef>
#include <string>
#include <wx/button.h>
#include <wx/choice.h>
#include <wx/msgdlg.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
2014-02-17 05:18:15 -05:00
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Core/ConfigManager.h"
2014-07-24 21:46:46 -04:00
#include "DolphinWX/WxUtils.h"
2014-02-17 05:18:15 -05:00
#include "DolphinWX/Debugger/DebuggerPanel.h"
2014-02-22 23:36:30 +01:00
#include "VideoCommon/Debugger.h"
2014-02-17 05:18:15 -05:00
#include "VideoCommon/TextureCacheBase.h"
2014-02-22 23:36:30 +01:00
2010-12-05 14:15:36 +00:00
GFXDebuggerPanel :: GFXDebuggerPanel ( wxWindow * parent , wxWindowID id , const wxPoint & position ,
const wxSize & size , long style , const wxString & title )
: wxPanel ( parent , id , position , size , style , title )
{
2011-01-31 04:36:49 +00:00
g_pdebugger = this ;
2010-12-05 14:15:36 +00:00
CreateGUIControls ();
2014-11-08 19:26:20 -05:00
Bind ( wxEVT_CLOSE_WINDOW , & GFXDebuggerPanel :: OnClose , this );
2010-12-05 14:15:36 +00:00
LoadSettings ();
}
GFXDebuggerPanel ::~ GFXDebuggerPanel ()
{
2014-03-09 21:14:26 +01:00
g_pdebugger = nullptr ;
2010-12-14 23:19:34 +00:00
GFXDebuggerPauseFlag = false ;
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnClose ( wxCloseEvent & event )
{
// save the window position when we hide the window
SaveSettings ();
2011-03-17 04:26:01 +00:00
event . Skip ();
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: SaveSettings () const
{
IniFile file ;
file . Load ( File :: GetUserPath ( F_DEBUGGERCONFIG_IDX ));
// TODO: make this work when we close the entire program too, currently on total close we get
// weird values, perhaps because of some conflict with the rendering window
2013-04-08 01:47:51 -04:00
2010-12-05 14:15:36 +00:00
// TODO: get the screen resolution and make limits from that
2014-03-11 00:30:55 +13:00
if ( GetPosition (). x < 1000 &&
GetPosition (). y < 1000 &&
GetSize (). GetWidth () < 1000 &&
GetSize (). GetHeight () < 1000 )
2010-12-05 14:15:36 +00:00
{
2014-06-16 01:12:43 -04:00
IniFile :: Section * video_window = file . GetOrCreateSection ( "VideoWindow" );
video_window -> Set ( "x" , GetPosition (). x );
video_window -> Set ( "y" , GetPosition (). y );
video_window -> Set ( "w" , GetSize (). GetWidth ());
video_window -> Set ( "h" , GetSize (). GetHeight ());
2010-12-05 14:15:36 +00:00
}
file . Save ( File :: GetUserPath ( F_DEBUGGERCONFIG_IDX ));
}
void GFXDebuggerPanel :: LoadSettings ()
{
IniFile file ;
file . Load ( File :: GetUserPath ( F_DEBUGGERCONFIG_IDX ));
2014-06-16 01:12:43 -04:00
int x = 100 ;
int y = 100 ;
int w = 100 ;
int h = 100 ;
IniFile :: Section * video_window = file . GetOrCreateSection ( "VideoWindow" );
video_window -> Get ( "x" , & x , GetPosition (). x );
video_window -> Get ( "y" , & y , GetPosition (). y );
video_window -> Get ( "w" , & w , GetSize (). GetWidth ());
video_window -> Get ( "h" , & h , GetSize (). GetHeight ());
2010-12-05 14:15:36 +00:00
SetSize ( x , y , w , h );
}
struct PauseEventMap
{
PauseEvent event ;
const wxString ListStr ;
};
2013-09-22 22:48:50 -04:00
static PauseEventMap * pauseEventMap ;
2010-12-05 14:15:36 +00:00
void GFXDebuggerPanel :: CreateGUIControls ()
{
2013-09-22 22:48:50 -04:00
static PauseEventMap map [] = {
2014-02-16 23:51:41 -05:00
{ NEXT_FRAME , _ ( "Frame" )},
{ NEXT_FLUSH , _ ( "Flush" )},
2013-09-22 22:48:50 -04:00
2014-02-16 23:51:41 -05:00
{ NEXT_PIXEL_SHADER_CHANGE , _ ( "Pixel Shader" )},
{ NEXT_VERTEX_SHADER_CHANGE , _ ( "Vertex Shader" )},
{ NEXT_TEXTURE_CHANGE , _ ( "Texture" )},
{ NEXT_NEW_TEXTURE , _ ( "New Texture" )},
2013-09-22 22:48:50 -04:00
2014-02-16 23:51:41 -05:00
{ NEXT_XFB_CMD , _ ( "XFB Cmd" )},
{ NEXT_EFB_CMD , _ ( "EFB Cmd" )},
2013-09-22 22:48:50 -04:00
2014-02-16 23:51:41 -05:00
{ NEXT_MATRIX_CMD , _ ( "Matrix Cmd" )},
{ NEXT_VERTEX_CMD , _ ( "Vertex Cmd" )},
{ NEXT_TEXTURE_CMD , _ ( "Texture Cmd" )},
{ NEXT_LIGHT_CMD , _ ( "Light Cmd" )},
{ NEXT_FOG_CMD , _ ( "Fog Cmd" )},
2013-09-22 22:48:50 -04:00
2014-02-16 23:51:41 -05:00
{ NEXT_SET_TLUT , _ ( "TLUT Cmd" )},
2013-09-22 22:48:50 -04:00
2014-02-16 23:51:41 -05:00
{ NEXT_ERROR , _ ( "Error" )}
2013-09-22 22:48:50 -04:00
};
pauseEventMap = map ;
const int numPauseEventMap = sizeof ( map ) / sizeof ( PauseEventMap );
2010-12-05 14:15:36 +00:00
// Basic settings
CenterOnParent ();
2014-11-08 19:26:20 -05:00
m_pButtonPause = new wxButton ( this , wxID_ANY , _ ( "Pause" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Pause" ));
m_pButtonPause -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnPauseButton , this );
2010-12-05 14:15:36 +00:00
2014-11-08 19:26:20 -05:00
m_pButtonPauseAtNext = new wxButton ( this , wxID_ANY , _ ( "Pause After" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Pause At Next" ));
m_pButtonPauseAtNext -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnPauseAtNextButton , this );
2010-12-05 14:15:36 +00:00
2014-11-08 19:26:20 -05:00
m_pButtonPauseAtNextFrame = new wxButton ( this , wxID_ANY , _ ( "Go to Next Frame" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Next Frame" ));
m_pButtonPauseAtNextFrame -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnPauseAtNextFrameButton , this );
m_pButtonCont = new wxButton ( this , wxID_ANY , _ ( "Continue" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Continue" ));
m_pButtonCont -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnContButton , this );
m_pCount = new wxTextCtrl ( this , wxID_ANY , "1" , wxDefaultPosition , wxSize ( 50 , 25 ), wxTE_RIGHT , wxDefaultValidator , _ ( "Count" ));
m_pPauseAtList = new wxChoice ( this , wxID_ANY , wxDefaultPosition , wxSize ( 100 , 25 ), 0 , nullptr , 0 , wxDefaultValidator , _ ( "PauseAtList" ));
2010-12-05 14:15:36 +00:00
for ( int i = 0 ; i < numPauseEventMap ; i ++ )
{
m_pPauseAtList -> Append ( pauseEventMap [ i ]. ListStr );
}
m_pPauseAtList -> SetSelection ( 0 );
2014-11-08 19:26:20 -05:00
m_pButtonDump = new wxButton ( this , wxID_ANY , _ ( "Dump" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Dump" ));
m_pButtonDump -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnDumpButton , this );
2010-12-05 14:15:36 +00:00
2014-11-08 19:26:20 -05:00
m_pButtonUpdateScreen = new wxButton ( this , wxID_ANY , _ ( "Update Screen" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Update Screen" ));
m_pButtonUpdateScreen -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnUpdateScreenButton , this );
m_pButtonClearScreen = new wxButton ( this , wxID_ANY , _ ( "Clear Screen" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Clear Screen" ));
m_pButtonClearScreen -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnClearScreenButton , this );
m_pButtonClearTextureCache = new wxButton ( this , wxID_ANY , _ ( "Clear Textures" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Clear Textures" ));
m_pButtonClearTextureCache -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnClearTextureCacheButton , this );
m_pButtonClearVertexShaderCache = new wxButton ( this , wxID_ANY , _ ( "Clear V Shaders" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Clear V Shaders" ));
m_pButtonClearVertexShaderCache -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnClearVertexShaderCacheButton , this );
m_pButtonClearPixelShaderCache = new wxButton ( this , wxID_ANY , _ ( "Clear P Shaders" ), wxDefaultPosition , wxDefaultSize , 0 , wxDefaultValidator , _ ( "Clear P Shaders" ));
m_pButtonClearPixelShaderCache -> Bind ( wxEVT_BUTTON , & GFXDebuggerPanel :: OnClearPixelShaderCacheButton , this );
m_pDumpList = new wxChoice ( this , wxID_ANY , wxDefaultPosition , wxSize ( 120 , 25 ), 0 , nullptr , 0 , wxDefaultValidator , _ ( "DumpList" ));
2011-01-05 04:35:46 +00:00
m_pDumpList -> Insert ( _ ( "Pixel Shader" ), 0 );
m_pDumpList -> Append ( _ ( "Vertex Shader" ));
m_pDumpList -> Append ( _ ( "Pixel Shader Constants" ));
m_pDumpList -> Append ( _ ( "Vertex Shader Constants" ));
m_pDumpList -> Append ( _ ( "Textures" ));
m_pDumpList -> Append ( _ ( "Frame Buffer" ));
m_pDumpList -> Append ( _ ( "Geometry data" ));
m_pDumpList -> Append ( _ ( "Vertex Description" ));
m_pDumpList -> Append ( _ ( "Vertex Matrices" ));
m_pDumpList -> Append ( _ ( "Statistics" ));
2010-12-05 14:15:36 +00:00
m_pDumpList -> SetSelection ( 0 );
// Layout everything on m_MainPanel
wxBoxSizer * sMain = new wxBoxSizer ( wxVERTICAL );
2011-07-01 20:59:57 +00:00
wxStaticBoxSizer * const pFlowCtrlBox = new wxStaticBoxSizer ( wxVERTICAL , this , _ ( "Flow Control" ));
wxBoxSizer * const pPauseAtNextSzr = new wxBoxSizer ( wxHORIZONTAL );
pFlowCtrlBox -> Add ( m_pButtonPause );
pPauseAtNextSzr -> Add ( m_pButtonPauseAtNext );
pPauseAtNextSzr -> Add ( m_pCount );
pPauseAtNextSzr -> Add ( m_pPauseAtList );
pFlowCtrlBox -> Add ( pPauseAtNextSzr );
pFlowCtrlBox -> Add ( m_pButtonPauseAtNextFrame );
pFlowCtrlBox -> Add ( m_pButtonCont );
wxStaticBoxSizer * const pDebugBox = new wxStaticBoxSizer ( wxVERTICAL , this , _ ( "Debugging" ));
wxBoxSizer * const pDumpSzr = new wxBoxSizer ( wxHORIZONTAL );
pDumpSzr -> Add ( m_pButtonDump );
pDumpSzr -> Add ( m_pDumpList );
pDebugBox -> Add ( pDumpSzr );
wxGridSizer * const pDbgGrid = new wxGridSizer ( 2 , 5 , 5 );
pDbgGrid -> Add ( m_pButtonUpdateScreen );
pDbgGrid -> Add ( m_pButtonClearScreen );
pDbgGrid -> Add ( m_pButtonClearTextureCache );
pDbgGrid -> Add ( m_pButtonClearVertexShaderCache );
pDbgGrid -> Add ( m_pButtonClearPixelShaderCache );
pDebugBox -> Add ( pDbgGrid );
sMain -> Add ( pFlowCtrlBox , 0 , 0 , 5 );
sMain -> Add ( pDebugBox , 0 , 0 , 5 );
SetSizerAndFit ( sMain );
2010-12-05 14:15:36 +00:00
OnContinue ();
}
void GFXDebuggerPanel :: OnPause ()
{
2015-02-14 16:00:15 -05:00
m_pButtonDump -> Enable ();
m_pDumpList -> Enable ();
m_pButtonUpdateScreen -> Enable ();
m_pButtonClearScreen -> Enable ();
m_pButtonClearTextureCache -> Enable ();
m_pButtonClearVertexShaderCache -> Enable ();
m_pButtonClearPixelShaderCache -> Enable ();
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnContinue ()
{
2015-02-14 16:00:15 -05:00
m_pButtonDump -> Disable ();
m_pDumpList -> Disable ();
m_pButtonUpdateScreen -> Disable ();
m_pButtonClearScreen -> Disable ();
m_pButtonClearTextureCache -> Disable ();
m_pButtonClearVertexShaderCache -> Disable ();
m_pButtonClearPixelShaderCache -> Disable ();
2010-12-05 14:15:36 +00:00
}
// General settings
void GFXDebuggerPanel :: GeneralSettings ( wxCommandEvent & event )
{
SaveSettings ();
}
void GFXDebuggerPanel :: OnPauseButton ( wxCommandEvent & event )
{
GFXDebuggerPauseFlag = true ;
}
void GFXDebuggerPanel :: OnPauseAtNextButton ( wxCommandEvent & event )
{
GFXDebuggerPauseFlag = false ;
GFXDebuggerToPauseAtNext = pauseEventMap [ m_pPauseAtList -> GetSelection ()]. event ;
wxString val = m_pCount -> GetValue ();
long value ;
if ( val . ToLong ( & value ))
GFXDebuggerEventToPauseCount = value ;
else
GFXDebuggerEventToPauseCount = 1 ;
}
void GFXDebuggerPanel :: OnPauseAtNextFrameButton ( wxCommandEvent & event )
{
GFXDebuggerPauseFlag = false ;
GFXDebuggerToPauseAtNext = NEXT_FRAME ;
GFXDebuggerEventToPauseCount = 1 ;
}
void GFXDebuggerPanel :: OnDumpButton ( wxCommandEvent & event )
{
2011-02-28 20:40:15 +00:00
std :: string dump_path = File :: GetUserPath ( D_DUMP_IDX ) + "Debug/" +
2015-06-12 13:56:53 +02:00
SConfig :: GetInstance (). m_strUniqueID + "/" ;
2011-03-01 03:06:14 +00:00
if ( ! File :: CreateFullPath ( dump_path ))
2010-12-14 23:19:34 +00:00
return ;
2010-12-05 14:15:36 +00:00
switch ( m_pDumpList -> GetSelection ())
{
case 0 : // Pixel Shader
2014-03-12 15:33:41 -04:00
DumpPixelShader ( dump_path );
2010-12-05 14:15:36 +00:00
break ;
case 1 : // Vertex Shader
2014-03-12 15:33:41 -04:00
DumpVertexShader ( dump_path );
2010-12-05 14:15:36 +00:00
break ;
case 2 : // Pixel Shader Constants
2014-03-12 15:33:41 -04:00
DumpPixelShaderConstants ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 3 : // Vertex Shader Constants
2014-03-12 15:33:41 -04:00
DumpVertexShaderConstants ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 4 : // Textures
2014-03-12 15:33:41 -04:00
DumpTextures ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 5 : // Frame Buffer
2014-03-12 15:33:41 -04:00
DumpFrameBuffer ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 6 : // Geometry
2014-03-12 15:33:41 -04:00
DumpGeometry ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 7 : // Vertex Description
2014-03-12 15:33:41 -04:00
DumpVertexDecl ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 8 : // Vertex Matrices
2014-03-12 15:33:41 -04:00
DumpMatrices ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
case 9 : // Statistics
2014-03-12 15:33:41 -04:00
DumpStats ( dump_path );
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
break ;
}
}
void GFXDebuggerPanel :: OnContButton ( wxCommandEvent & event )
{
GFXDebuggerToPauseAtNext = NOT_PAUSE ;
GFXDebuggerPauseFlag = false ;
}
void GFXDebuggerPanel :: OnClearScreenButton ( wxCommandEvent & event )
{
// TODO
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnClearTextureCacheButton ( wxCommandEvent & event )
{
2012-05-28 11:37:14 +02:00
TextureCache :: Invalidate ();
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnClearVertexShaderCacheButton ( wxCommandEvent & event )
{
// TODO
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnClearPixelShaderCacheButton ( wxCommandEvent & event )
{
// TODO
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
}
void GFXDebuggerPanel :: OnUpdateScreenButton ( wxCommandEvent & event )
{
2014-07-24 21:46:46 -04:00
WxUtils :: ShowErrorDialog ( _ ( "Not implemented" ));
2010-12-05 14:15:36 +00:00
GFXDebuggerUpdateScreen ();
}