1 // Copyright (C) 2003 Dolphin Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official SVN repository and contact information can be found at
16 // http://code.google.com/p/dolphin-emu/
21 #include "LogManager.h"
22 #include "debugger/debugger.h"
24 #if defined(HAVE_WX) && HAVE_WX
25 #include "DlgSettings.h"
26 GFXConfigDialogDX
*m_ConfigFrame
= NULL
;
29 #if defined(HAVE_WX) && HAVE_WX
30 #include "Debugger/Debugger.h"
34 #include "VideoConfig.h"
36 #include "OpcodeDecoding.h"
37 #include "TextureCache.h"
38 #include "BPStructs.h"
39 #include "VertexManager.h"
40 #include "VertexLoaderManager.h"
41 #include "VertexShaderManager.h"
42 #include "PixelShaderManager.h"
43 #include "VertexShaderCache.h"
44 #include "PixelShaderCache.h"
45 #include "CommandProcessor.h"
46 #include "PixelEngine.h"
47 #include "OnScreenDisplay.h"
48 #include "DlgSettings.h"
49 #include "D3DTexture.h"
51 #include "EmuWindow.h"
52 #include "VideoState.h"
53 #include "XFBConvert.h"
56 HINSTANCE g_hInstance
= NULL
;
57 SVideoInitialize g_VideoInitialize
;
58 PLUGIN_GLOBALS
* globals
= NULL
;
59 static bool s_PluginInitialized
= false;
61 volatile u32 s_swapRequested
= FALSE
;
62 static u32 s_efbAccessRequested
= FALSE
;
63 static volatile u32 s_FifoShuttingDown
= FALSE
;
65 static volatile struct
73 static volatile EFBAccessType s_AccessEFBType
;
75 bool HandleDisplayList(u32 address
, u32 size
)
85 // This is used for the functions right below here which use wxwidgets
86 #if defined(HAVE_WX) && HAVE_WX
87 WXDLLIMPEXP_BASE
void wxSetInstance(HINSTANCE hInst
);
90 void *DllDebugger(void *_hParent
, bool Show
)
92 #if defined(HAVE_WX) && HAVE_WX
93 return new GFXDebuggerDX9((wxWindow
*)_hParent
);
99 #if defined(HAVE_WX) && HAVE_WX
100 class wxDLLApp
: public wxApp
107 IMPLEMENT_APP_NO_MAIN(wxDLLApp
)
108 WXDLLIMPEXP_BASE
void wxSetInstance(HINSTANCE hInst
);
111 BOOL APIENTRY
DllMain(HINSTANCE hinstDLL
, DWORD dwReason
, LPVOID lpvReserved
)
115 case DLL_PROCESS_ATTACH
:
117 #if defined(HAVE_WX) && HAVE_WX
118 wxSetInstance((HINSTANCE
)hinstDLL
);
123 case DLL_PROCESS_DETACH
:
124 #if defined(HAVE_WX) && HAVE_WX
130 g_hInstance
= hinstDLL
;
134 unsigned int Callback_PeekMessages()
137 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
139 if (msg
.message
== WM_QUIT
)
141 TranslateMessage(&msg
);
142 DispatchMessage(&msg
);
148 void UpdateFPSDisplay(const char *text
)
151 swprintf_s(temp
, 512, _T("SVN R%s: DX9: %hs"), svn_rev_str
, text
);
152 SetWindowText(EmuWindow::GetWnd(), temp
);
155 void GetDllInfo (PLUGIN_INFO
* _PluginInfo
)
157 _PluginInfo
->Version
= 0x0100;
158 _PluginInfo
->Type
= PLUGIN_TYPE_VIDEO
;
160 sprintf_s(_PluginInfo
->Name
, 100, "Dolphin Direct3D9 (DebugFast)");
163 sprintf_s(_PluginInfo
->Name
, 100, "Dolphin Direct3D9");
165 sprintf_s(_PluginInfo
->Name
, 100, "Dolphin Direct3D9 (Debug)");
170 void SetDllGlobals(PLUGIN_GLOBALS
* _pPluginGlobals
)
172 globals
= _pPluginGlobals
;
173 LogManager::SetInstance((LogManager
*)globals
->logManager
);
176 void DllAbout(HWND _hParent
)
178 //DialogBox(g_hInstance,(LPCTSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
181 void DllConfig(void *_hParent
)
183 // If not initialized, only init D3D so we can enumerate resolutions.
184 if (!s_PluginInitialized
)
186 g_Config
.Load((std::string(File::GetUserPath(D_CONFIG_IDX
)) + "gfx_dx9.ini").c_str());
187 g_Config
.GameIniLoad(globals
->game_ini
);
188 UpdateActiveConfig();
189 #if defined(HAVE_WX) && HAVE_WX
190 m_ConfigFrame
= new GFXConfigDialogDX((wxWindow
*)_hParent
);
192 m_ConfigFrame
->CreateGUIControls();
193 m_ConfigFrame
->ShowModal();
194 m_ConfigFrame
->Destroy();
196 if (!s_PluginInitialized
)
200 void Initialize(void *init
)
203 SVideoInitialize
*_pVideoInitialize
= (SVideoInitialize
*)init
;
204 g_VideoInitialize
= *_pVideoInitialize
;
207 g_Config
.Load((std::string(File::GetUserPath(D_CONFIG_IDX
)) + "gfx_dx9.ini").c_str());
208 g_Config
.GameIniLoad(globals
->game_ini
);
209 UpdateProjectionHack(g_Config
.iPhackvalue
); // DX9 projection hack could be disabled by commenting out this line
210 UpdateActiveConfig();
212 g_VideoInitialize
.pWindowHandle
= (void*)EmuWindow::Create((HWND
)g_VideoInitialize
.pWindowHandle
, g_hInstance
, _T("Loading - Please wait."));
213 if (g_VideoInitialize
.pWindowHandle
== NULL
)
215 ERROR_LOG(VIDEO
, "An error has occurred while trying to create the window.");
218 else if (FAILED(D3D::Init()))
220 MessageBox(GetActiveWindow(), _T("Unable to initialize Direct3D. Please make sure that you have the latest version of DirectX 9.0c correctly installed."), _T("Fatal Error"), MB_ICONERROR
|MB_OK
);
224 g_VideoInitialize
.pPeekMessages
= &Callback_PeekMessages
;
225 g_VideoInitialize
.pUpdateFPSDisplay
= &UpdateFPSDisplay
;
227 _pVideoInitialize
->pPeekMessages
= g_VideoInitialize
.pPeekMessages
;
228 _pVideoInitialize
->pUpdateFPSDisplay
= g_VideoInitialize
.pUpdateFPSDisplay
;
229 _pVideoInitialize
->pWindowHandle
= g_VideoInitialize
.pWindowHandle
;
231 OSD::AddMessage("Dolphin Direct3D9 Video Plugin.", 5000);
232 s_PluginInitialized
= true;
238 s_efbAccessRequested
= FALSE
;
239 s_FifoShuttingDown
= FALSE
;
240 s_swapRequested
= FALSE
;
242 TextureCache::Init();
244 VertexManager::Init();
246 VertexLoaderManager::Init();
247 OpcodeDecoder_Init();
248 VertexShaderManager::Init();
249 PixelShaderManager::Init();
250 CommandProcessor::Init();
253 // Tell the host the window is ready
254 g_VideoInitialize
.pCoreMessage(WM_USER_CREATE
);
259 s_efbAccessRequested
= FALSE
;
260 s_FifoShuttingDown
= FALSE
;
261 s_swapRequested
= FALSE
;
263 CommandProcessor::Shutdown();
264 VertexManager::Shutdown();
265 VertexLoaderManager::Shutdown();
266 VertexShaderManager::Shutdown();
267 PixelShaderManager::Shutdown();
268 TextureCache::Shutdown();
269 OpcodeDecoder_Shutdown();
270 Renderer::Shutdown();
273 s_PluginInitialized
= false;
276 void DoState(unsigned char **ptr
, int mode
) {
277 // Clear texture cache because it might have written to RAM
278 CommandProcessor::FifoCriticalEnter();
279 TextureCache::Invalidate(false);
280 CommandProcessor::FifoCriticalLeave();
281 // No need to clear shader caches.
282 PointerWrap
p(ptr
, mode
);
283 VideoCommon_DoState(p
);
286 void EmuStateChange(PLUGIN_EMUSTATE newState
)
288 Fifo_RunLoop((newState
== PLUGIN_EMUSTATE_PLAY
) ? true : false);
291 void Video_EnterLoop()
293 Fifo_EnterLoop(g_VideoInitialize
);
296 void Video_ExitLoop()
300 s_FifoShuttingDown
= TRUE
;
303 void Video_SetRendering(bool bEnabled
) {
304 Fifo_SetRendering(bEnabled
);
307 // Run from the graphics thread (from Fifo.cpp)
308 void VideoFifo_CheckSwapRequest()
310 if(g_ActiveConfig
.bUseXFB
)
312 if (Common::AtomicLoadAcquire(s_swapRequested
))
315 Renderer::Swap(s_beginFieldArgs
.xfbAddr
, s_beginFieldArgs
.field
, s_beginFieldArgs
.fbWidth
, s_beginFieldArgs
.fbHeight
,rc
);
316 Common::AtomicStoreRelease(s_swapRequested
, FALSE
);
321 inline bool addrRangesOverlap(u32 aLower
, u32 aUpper
, u32 bLower
, u32 bUpper
)
323 return !((aLower
>= bUpper
) || (bLower
>= aUpper
));
326 // Run from the graphics thread (from Fifo.cpp)
327 void VideoFifo_CheckSwapRequestAt(u32 xfbAddr
, u32 fbWidth
, u32 fbHeight
)
329 if (g_ActiveConfig
.bUseXFB
)
331 if(Common::AtomicLoadAcquire(s_swapRequested
))
333 u32 aLower
= xfbAddr
;
334 u32 aUpper
= xfbAddr
+ 2 * fbWidth
* fbHeight
;
335 u32 bLower
= s_beginFieldArgs
.xfbAddr
;
336 u32 bUpper
= s_beginFieldArgs
.xfbAddr
+ 2 * s_beginFieldArgs
.fbWidth
* s_beginFieldArgs
.fbHeight
;
338 if (addrRangesOverlap(aLower
, aUpper
, bLower
, bUpper
))
339 VideoFifo_CheckSwapRequest();
344 // Run from the CPU thread (from VideoInterface.cpp)
345 void Video_BeginField(u32 xfbAddr
, FieldType field
, u32 fbWidth
, u32 fbHeight
)
347 if (s_PluginInitialized
&& g_ActiveConfig
.bUseXFB
)
349 if (g_VideoInitialize
.bOnThread
)
351 while (Common::AtomicLoadAcquire(s_swapRequested
) && !s_FifoShuttingDown
)
352 //Common::SleepCurrentThread(1);
356 VideoFifo_CheckSwapRequest();
357 s_beginFieldArgs
.xfbAddr
= xfbAddr
;
358 s_beginFieldArgs
.field
= field
;
359 s_beginFieldArgs
.fbWidth
= fbWidth
;
360 s_beginFieldArgs
.fbHeight
= fbHeight
;
362 Common::AtomicStoreRelease(s_swapRequested
, TRUE
);
366 void Video_EndField()
370 void Video_AddMessage(const char* pstr
, u32 milliseconds
)
372 OSD::AddMessage(pstr
,milliseconds
);
375 HRESULT
ScreenShot(const char *File
)
377 Renderer::SetScreenshot(File
);
381 void Video_Screenshot(const char *_szFilename
)
383 if (ScreenShot(_szFilename
) != S_OK
)
384 PanicAlert("Error while capturing screen");
386 std::string message
= "Saved ";
387 message
+= _szFilename
;
388 OSD::AddMessage(message
.c_str(), 2000);
400 static u32 s_AccessEFBResult
= 0;
402 void VideoFifo_CheckEFBAccess()
404 if (Common::AtomicLoadAcquire(s_efbAccessRequested
))
406 s_AccessEFBResult
= Renderer::AccessEFB(s_accessEFBArgs
.type
, s_accessEFBArgs
.x
, s_accessEFBArgs
.y
);
408 Common::AtomicStoreRelease(s_efbAccessRequested
, FALSE
);
412 u32
Video_AccessEFB(EFBAccessType type
, u32 x
, u32 y
,u32 InputData
)
414 if (s_PluginInitialized
)
416 s_accessEFBArgs
.type
= type
;
417 s_accessEFBArgs
.x
= x
;
418 s_accessEFBArgs
.y
= y
;
419 s_accessEFBArgs
.Data
= InputData
;
421 Common::AtomicStoreRelease(s_efbAccessRequested
, TRUE
);
423 if (g_VideoInitialize
.bOnThread
)
425 while (Common::AtomicLoadAcquire(s_efbAccessRequested
) && !s_FifoShuttingDown
)
426 //Common::SleepCurrentThread(1);
430 VideoFifo_CheckEFBAccess();
432 return s_AccessEFBResult
;
439 void Video_CommandProcessorRead16(u16
& _rReturnValue
, const u32 _Address
)
441 CommandProcessor::Read16(_rReturnValue
, _Address
);
444 void Video_CommandProcessorWrite16(const u16 _Data
, const u32 _Address
)
446 CommandProcessor::Write16(_Data
, _Address
);
449 void Video_PixelEngineRead16(u16
& _rReturnValue
, const u32 _Address
)
451 PixelEngine::Read16(_rReturnValue
, _Address
);
454 void Video_PixelEngineWrite16(const u16 _Data
, const u32 _Address
)
456 PixelEngine::Write16(_Data
, _Address
);
459 void Video_PixelEngineWrite32(const u32 _Data
, const u32 _Address
)
461 PixelEngine::Write32(_Data
, _Address
);
464 inline void Video_GatherPipeBursted(void)
466 CommandProcessor::GatherPipeBursted();
469 void Video_WaitForFrameFinish(void)
471 CommandProcessor::WaitForFrameFinish();
474 bool Video_IsFifoBusy(void)
476 return CommandProcessor::isFifoBusy
;