Move fullscreen display resolution control to the GUI with the rest of the fullscreen...
[dolphin.git] / Source / Plugins / Plugin_VideoDX9 / Src / main.cpp
blob8c8c0afc3bde539b0897efa75c5d841b5047ea22
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/
18 #include <tchar.h>
19 #include <windows.h>
20 #include <d3dx9.h>
22 #include "Common.h"
23 #include "Atomic.h"
24 #include "Thread.h"
25 #include "LogManager.h"
26 #include "debugger/debugger.h"
28 #if defined(HAVE_WX) && HAVE_WX
29 #include "Debugger/Debugger.h"
30 GFXDebuggerDX9 *m_DebuggerFrame = NULL;
31 #endif // HAVE_WX
33 #include "svnrev.h"
34 #include "resource.h"
35 #include "main.h"
36 #include "VideoConfig.h"
37 #include "Fifo.h"
38 #include "OpcodeDecoding.h"
39 #include "TextureCache.h"
40 #include "BPStructs.h"
41 #include "VertexManager.h"
42 #include "VertexLoaderManager.h"
43 #include "VertexShaderManager.h"
44 #include "PixelShaderManager.h"
45 #include "VertexShaderCache.h"
46 #include "PixelShaderCache.h"
47 #include "CommandProcessor.h"
48 #include "PixelEngine.h"
49 #include "OnScreenDisplay.h"
50 #include "DlgSettings.h"
51 #include "D3DTexture.h"
52 #include "D3DUtil.h"
53 #include "W32Util/Misc.h"
54 #include "EmuWindow.h"
55 #include "VideoState.h"
56 #include "XFBConvert.h"
57 #include "render.h"
60 #include "Utils.h"
62 HINSTANCE g_hInstance = NULL;
63 SVideoInitialize g_VideoInitialize;
64 PLUGIN_GLOBALS* globals = NULL;
65 static bool s_PluginInitialized = false;
67 volatile u32 s_swapRequested = FALSE;
68 static u32 s_efbAccessRequested = FALSE;
69 static volatile u32 s_FifoShuttingDown = FALSE;
70 static bool ForceSwap = true;
72 static volatile struct
74 u32 xfbAddr;
75 FieldType field;
76 u32 fbWidth;
77 u32 fbHeight;
78 } s_beginFieldArgs;
80 static volatile EFBAccessType s_AccessEFBType;
82 bool HandleDisplayList(u32 address, u32 size)
84 return false;
87 bool IsD3D()
89 return true;
92 // This is used for the functions right below here which use wxwidgets
93 #if defined(HAVE_WX) && HAVE_WX
94 #ifdef _WIN32
95 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
96 #endif
98 wxWindow* GetParentedWxWindow(HWND Parent)
100 #ifdef _WIN32
101 wxSetInstance((HINSTANCE)g_hInstance);
102 #endif
103 wxWindow *win = new wxWindow();
104 #ifdef _WIN32
105 win->SetHWND((WXHWND)Parent);
106 win->AdoptAttributesFromHWND();
107 #endif
108 return win;
110 #endif
112 void DllDebugger(HWND _hParent, bool Show)
114 #if defined(HAVE_WX) && HAVE_WX
115 if (!m_DebuggerFrame)
116 m_DebuggerFrame = new GFXDebuggerDX9(GetParentedWxWindow(_hParent));
118 if (Show)
119 m_DebuggerFrame->Show();
120 else
121 m_DebuggerFrame->Hide();
122 #endif
125 #if defined(HAVE_WX) && HAVE_WX
126 class wxDLLApp : public wxApp
128 bool OnInit()
130 return true;
133 IMPLEMENT_APP_NO_MAIN(wxDLLApp)
134 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
135 #endif
137 BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpvReserved)
139 switch (dwReason)
141 case DLL_PROCESS_ATTACH:
143 #if defined(HAVE_WX) && HAVE_WX
144 wxSetInstance((HINSTANCE)hinstDLL);
145 wxInitialize();
146 #endif
148 break;
149 case DLL_PROCESS_DETACH:
150 #if defined(HAVE_WX) && HAVE_WX
151 wxUninitialize();
152 #endif
153 break;
156 g_hInstance = hinstDLL;
157 return TRUE;
160 unsigned int Callback_PeekMessages()
162 MSG msg;
163 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
165 if (msg.message == WM_QUIT)
166 return FALSE;
167 TranslateMessage(&msg);
168 DispatchMessage(&msg);
170 return TRUE;
174 void UpdateFPSDisplay(const char *text)
176 char temp[512];
177 sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
178 SetWindowTextA(EmuWindow::GetWnd(), temp);
181 void GetDllInfo (PLUGIN_INFO* _PluginInfo)
183 _PluginInfo->Version = 0x0100;
184 _PluginInfo->Type = PLUGIN_TYPE_VIDEO;
185 #ifdef DEBUGFAST
186 sprintf_s(_PluginInfo->Name, 100, "Dolphin Direct3D9 (DebugFast)");
187 #else
188 #ifndef _DEBUG
189 sprintf_s(_PluginInfo->Name, 100, "Dolphin Direct3D9");
190 #else
191 sprintf_s(_PluginInfo->Name, 100, "Dolphin Direct3D9 (Debug)");
192 #endif
193 #endif
196 void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals) {
197 globals = _pPluginGlobals;
198 LogManager::SetInstance((LogManager *)globals->logManager);
201 void DllAbout(HWND _hParent)
203 DialogBox(g_hInstance,(LPCTSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
206 void DllConfig(HWND _hParent)
208 // If not initialized, only init D3D so we can enumerate resolutions.
209 if (!s_PluginInitialized) D3D::Init();
210 DlgSettings_Show(g_hInstance, _hParent);
211 if (!s_PluginInitialized) D3D::Shutdown();
214 void Initialize(void *init)
216 frameCount = 0;
217 SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
218 g_VideoInitialize = *_pVideoInitialize;
219 InitXFBConvTables();
221 g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_dx9.ini").c_str());
222 g_Config.GameIniLoad(globals->game_ini);
223 UpdateProjectionHack(g_Config.iPhackvalue); // DX9 projection hack could be disabled by commenting out this line
224 UpdateActiveConfig();
226 g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, _T("Loading - Please wait."));
227 if (g_VideoInitialize.pWindowHandle == NULL)
229 ERROR_LOG(VIDEO, "An error has occurred while trying to create the window.");
230 return;
232 else if (FAILED(D3D::Init()))
234 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_OK);
235 return;
238 g_VideoInitialize.pPeekMessages = &Callback_PeekMessages;
239 g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay;
241 _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
242 _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
243 _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
245 OSD::AddMessage("Dolphin Direct3D9 Video Plugin.", 5000);
246 s_PluginInitialized = true;
249 void Video_Prepare()
251 // Better be safe...
252 s_efbAccessRequested = FALSE;
253 s_FifoShuttingDown = FALSE;
254 s_swapRequested = FALSE;
255 ForceSwap = true;
256 Renderer::Init();
257 TextureCache::Init();
258 BPInit();
259 VertexManager::Init();
260 Fifo_Init();
261 VertexLoaderManager::Init();
262 OpcodeDecoder_Init();
263 VertexShaderCache::Init();
264 VertexShaderManager::Init();
265 PixelShaderCache::Init();
266 PixelShaderManager::Init();
267 CommandProcessor::Init();
268 PixelEngine::Init();
270 // Tell the host the window is ready
271 g_VideoInitialize.pCoreMessage(WM_USER_CREATE);
274 void Shutdown()
276 s_efbAccessRequested = FALSE;
277 s_FifoShuttingDown = FALSE;
278 s_swapRequested = FALSE;
279 Fifo_Shutdown();
280 VertexManager::Shutdown();
281 VertexLoaderManager::Shutdown();
282 VertexShaderCache::Shutdown();
283 VertexShaderManager::Shutdown();
284 PixelShaderCache::Shutdown();
285 PixelShaderManager::Shutdown();
286 TextureCache::Shutdown();
287 OpcodeDecoder_Shutdown();
288 Renderer::Shutdown();
289 D3D::Shutdown();
290 EmuWindow::Close();
291 s_PluginInitialized = false;
294 void DoState(unsigned char **ptr, int mode) {
295 // Clear texture cache because it might have written to RAM
296 CommandProcessor::FifoCriticalEnter();
297 TextureCache::Invalidate(false);
298 CommandProcessor::FifoCriticalLeave();
299 // No need to clear shader caches.
300 PointerWrap p(ptr, mode);
301 VideoCommon_DoState(p);
304 void EmuStateChange(PLUGIN_EMUSTATE newState)
306 Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
309 void Video_EnterLoop()
311 Fifo_EnterLoop(g_VideoInitialize);
314 void Video_ExitLoop()
316 Fifo_ExitLoop();
318 s_FifoShuttingDown = TRUE;
321 void Video_SetRendering(bool bEnabled) {
322 Fifo_SetRendering(bEnabled);
325 // Run from the graphics thread
326 void VideoFifo_CheckSwapRequest()
328 if (Common::AtomicLoadAcquire(s_swapRequested))
330 if (ForceSwap || g_ActiveConfig.bUseXFB)
332 Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
335 Common::AtomicStoreRelease(s_swapRequested, FALSE);
339 inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
341 return !((aLower >= bUpper) || (bLower >= aUpper));
344 // Run from the graphics thread
345 void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
347 if (Common::AtomicLoadAcquire(s_swapRequested) && g_ActiveConfig.bUseXFB)
349 u32 aLower = xfbAddr;
350 u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
351 u32 bLower = s_beginFieldArgs.xfbAddr;
352 u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbWidth * s_beginFieldArgs.fbHeight;
354 if (addrRangesOverlap(aLower, aUpper, bLower, bUpper))
355 VideoFifo_CheckSwapRequest();
358 ForceSwap = false;
361 // Run from the CPU thread (from VideoInterface.cpp)
362 void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
364 if (s_PluginInitialized && g_ActiveConfig.bUseXFB)
366 s_beginFieldArgs.xfbAddr = xfbAddr;
367 s_beginFieldArgs.field = field;
368 s_beginFieldArgs.fbWidth = fbWidth;
369 s_beginFieldArgs.fbHeight = fbHeight;
371 Common::AtomicStoreRelease(s_swapRequested, TRUE);
372 if (g_VideoInitialize.bOnThread)
374 while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown)
375 //Common::SleepCurrentThread(1);
376 Common::YieldCPU();
378 else
379 VideoFifo_CheckSwapRequest();
383 void Video_EndField()
387 void Video_AddMessage(const char* pstr, u32 milliseconds)
389 OSD::AddMessage(pstr,milliseconds);
392 HRESULT ScreenShot(const char *File)
394 Renderer::SetScreenshot(File);
395 return S_OK;
398 void Video_Screenshot(const char *_szFilename)
400 if (ScreenShot(_szFilename) != S_OK)
401 PanicAlert("Error while capturing screen");
402 else {
403 std::string message = "Saved ";
404 message += _szFilename;
405 OSD::AddMessage(message.c_str(), 2000);
409 static struct
411 EFBAccessType type;
412 u32 x;
413 u32 y;
414 } s_accessEFBArgs;
416 static u32 s_AccessEFBResult = 0;
418 void VideoFifo_CheckEFBAccess()
420 if (Common::AtomicLoadAcquire(s_efbAccessRequested))
422 s_AccessEFBResult = Renderer::AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y);
424 Common::AtomicStoreRelease(s_efbAccessRequested, FALSE);
428 u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
430 if (s_PluginInitialized)
432 s_accessEFBArgs.type = type;
433 s_accessEFBArgs.x = x;
434 s_accessEFBArgs.y = y;
436 Common::AtomicStoreRelease(s_efbAccessRequested, TRUE);
438 if (g_VideoInitialize.bOnThread)
440 while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown)
441 //Common::SleepCurrentThread(1);
442 Common::YieldCPU();
444 else
445 VideoFifo_CheckEFBAccess();
447 return s_AccessEFBResult;
450 return 0;
454 void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
456 CommandProcessor::Read16(_rReturnValue, _Address);
459 void Video_CommandProcessorWrite16(const u16 _Data, const u32 _Address)
461 CommandProcessor::Write16(_Data, _Address);
464 void Video_PixelEngineRead16(u16& _rReturnValue, const u32 _Address)
466 PixelEngine::Read16(_rReturnValue, _Address);
469 void Video_PixelEngineWrite16(const u16 _Data, const u32 _Address)
471 PixelEngine::Write16(_Data, _Address);
474 void Video_PixelEngineWrite32(const u32 _Data, const u32 _Address)
476 PixelEngine::Write32(_Data, _Address);
479 inline void Video_GatherPipeBursted(void)
481 CommandProcessor::GatherPipeBursted();
484 void Video_WaitForFrameFinish(void)
486 CommandProcessor::WaitForFrameFinish();