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/
23 #include <wx/notebook.h>
28 #include "LogManager.h"
30 #include "VideoConfig.h"
32 #include "OpcodeDecoding.h"
33 #include "BPStructs.h"
34 #include "VertexLoaderManager.h"
35 #include "VertexShaderManager.h"
36 #include "PixelShaderManager.h"
37 #include "CommandProcessor.h"
38 #include "PixelEngine.h"
39 #include "OnScreenDisplay.h"
40 #include "VideoState.h"
41 #include "XFBConvert.h"
46 #include "DlgSettings.h"
47 #include "TextureCache.h"
48 #include "VertexManager.h"
49 #include "VertexShaderCache.h"
50 #include "PixelShaderCache.h"
51 #include "D3DTexture.h"
53 #include "W32Util/Misc.h"
54 #include "EmuWindow.h"
55 #include "FBManager.h"
58 #if defined(DEBUGFAST)
59 #define DLL_PLUGIN_NAME "Dolphin Direct3D 11 (DebugFast)"
61 #define DLL_PLUGIN_NAME "Dolphin Direct3D 11 (Debug)"
63 #define DLL_PLUGIN_NAME "Dolphin Direct3D 11"
67 HINSTANCE g_hInstance
= NULL
;
68 SVideoInitialize g_VideoInitialize
;
69 PLUGIN_GLOBALS
* globals
= NULL
;
70 static bool s_PluginInitialized
= false;
72 volatile u32 s_swapRequested
= FALSE
;
73 static u32 s_efbAccessRequested
= FALSE
;
74 static volatile u32 s_FifoShuttingDown
= FALSE
;
76 static volatile struct
84 static volatile EFBAccessType s_AccessEFBType
;
86 bool HandleDisplayList(u32 address
, u32 size
)
96 // This is used for the functions right below here which use wxwidgets
97 #if defined(HAVE_WX) && HAVE_WX
98 WXDLLIMPEXP_BASE
void wxSetInstance(HINSTANCE hInst
);
100 wxWindow
* GetParentedWxWindow(HWND Parent
)
102 wxSetInstance((HINSTANCE
)g_hInstance
);
103 wxWindow
* win
= new wxWindow();
104 win
->SetHWND((WXHWND
)Parent
);
105 win
->AdoptAttributesFromHWND();
110 void *DllDebugger(void *_hParent
, bool Show
)
115 #if defined(HAVE_WX) && HAVE_WX
116 class wxDLLApp
: public wxApp
123 IMPLEMENT_APP_NO_MAIN(wxDLLApp
)
124 WXDLLIMPEXP_BASE
void wxSetInstance(HINSTANCE hInst
);
127 BOOL APIENTRY
DllMain(HINSTANCE hinstDLL
, DWORD dwReason
, LPVOID lpvReserved
)
131 case DLL_PROCESS_ATTACH
:
133 #if defined(HAVE_WX) && HAVE_WX
134 wxSetInstance((HINSTANCE
)hinstDLL
);
139 case DLL_PROCESS_DETACH
:
140 #if defined(HAVE_WX) && HAVE_WX
146 g_hInstance
= hinstDLL
;
150 unsigned int Callback_PeekMessages()
153 while (PeekMessage(&msg
, 0, 0, 0, PM_REMOVE
))
155 if (msg
.message
== WM_QUIT
)
157 TranslateMessage(&msg
);
158 DispatchMessage(&msg
);
164 void UpdateFPSDisplay(const char* text
)
167 sprintf_s(temp
, 512, "SVN R%s: DX11: %s", svn_rev_str
, text
);
168 SetWindowTextA(EmuWindow::GetWnd(), temp
);
171 void GetDllInfo(PLUGIN_INFO
* _PluginInfo
)
173 _PluginInfo
->Version
= 0x0100;
174 _PluginInfo
->Type
= PLUGIN_TYPE_VIDEO
;
175 sprintf_s(_PluginInfo
->Name
, 100, DLL_PLUGIN_NAME
);
178 void SetDllGlobals(PLUGIN_GLOBALS
* _pPluginGlobals
)
180 globals
= _pPluginGlobals
;
181 LogManager::SetInstance((LogManager
*)globals
->logManager
);
184 void DllAbout(HWND _hParent
)
186 MessageBoxA(NULL
, "DllAbout not implemented, how did you come here? Anyway, report this to the devs.", "Error!", MB_OK
);
189 void DllConfig(HWND _hParent
)
191 DlgSettings_Show(g_hInstance
, _hParent
);
194 void Initialize(void* init
)
197 SVideoInitialize
* _pVideoInitialize
= (SVideoInitialize
*)init
;
198 g_VideoInitialize
= *_pVideoInitialize
;
201 g_Config
.Load((std::string(File::GetUserPath(D_CONFIG_IDX
)) + "gfx_dx11.ini").c_str());
202 g_Config
.GameIniLoad(globals
->game_ini
);
203 UpdateActiveConfig();
205 g_VideoInitialize
.pWindowHandle
= (void*)EmuWindow::Create((HWND
)g_VideoInitialize
.pWindowHandle
, g_hInstance
, _T("Loading - Please wait."));
206 if (g_VideoInitialize
.pWindowHandle
== NULL
)
208 ERROR_LOG(VIDEO
, "An error has occurred while trying to create the window.");
212 g_VideoInitialize
.pPeekMessages
= &Callback_PeekMessages
;
213 g_VideoInitialize
.pUpdateFPSDisplay
= &UpdateFPSDisplay
;
215 _pVideoInitialize
->pPeekMessages
= g_VideoInitialize
.pPeekMessages
;
216 _pVideoInitialize
->pUpdateFPSDisplay
= g_VideoInitialize
.pUpdateFPSDisplay
;
217 _pVideoInitialize
->pWindowHandle
= g_VideoInitialize
.pWindowHandle
;
219 OSD::AddMessage("Dolphin Direct3D 11 Video Plugin.", 5000);
220 s_PluginInitialized
= true;
225 s_efbAccessRequested
= FALSE
;
226 s_FifoShuttingDown
= FALSE
;
227 s_swapRequested
= FALSE
;
229 // internal interfaces
231 TextureCache::Init();
232 VertexManager::Init();
233 VertexShaderCache::Init();
234 PixelShaderCache::Init();
240 VertexLoaderManager::Init();
241 OpcodeDecoder_Init();
242 VertexShaderManager::Init();
243 PixelShaderManager::Init();
244 CommandProcessor::Init();
247 // tell the host that the window is ready
248 g_VideoInitialize
.pCoreMessage(WM_USER_CREATE
);
253 s_efbAccessRequested
= FALSE
;
254 s_FifoShuttingDown
= FALSE
;
255 s_swapRequested
= FALSE
;
258 CommandProcessor::Shutdown();
259 PixelShaderManager::Shutdown();
260 VertexShaderManager::Shutdown();
261 OpcodeDecoder_Shutdown();
262 VertexLoaderManager::Shutdown();
265 // internal interfaces
266 D3D::ShutdownUtils();
267 PixelShaderCache::Shutdown();
268 VertexShaderCache::Shutdown();
269 VertexManager::Shutdown();
270 TextureCache::Shutdown();
271 Renderer::Shutdown();
274 s_PluginInitialized
= false;
277 void DoState(unsigned char** ptr
, int mode
)
279 // clear texture cache because it might have written to RAM
280 CommandProcessor::FifoCriticalEnter();
281 TextureCache::Invalidate(false);
282 CommandProcessor::FifoCriticalLeave();
283 // no need to clear shader caches
284 PointerWrap
p(ptr
, mode
);
285 VideoCommon_DoState(p
);
288 void EmuStateChange(PLUGIN_EMUSTATE newState
)
290 Fifo_RunLoop((newState
== PLUGIN_EMUSTATE_PLAY
) ? true : false);
293 void Video_EnterLoop()
295 Fifo_EnterLoop(g_VideoInitialize
);
298 void Video_ExitLoop()
301 s_FifoShuttingDown
= TRUE
;
304 void Video_SetRendering(bool bEnabled
)
306 Fifo_SetRendering(bEnabled
);
309 // Run from the graphics thread (from Fifo.cpp)
310 void VideoFifo_CheckSwapRequest()
312 if(g_ActiveConfig
.bUseXFB
)
314 if (Common::AtomicLoadAcquire(s_swapRequested
))
317 Renderer::Swap(s_beginFieldArgs
.xfbAddr
, s_beginFieldArgs
.field
, s_beginFieldArgs
.fbWidth
, s_beginFieldArgs
.fbHeight
,rc
);
318 Common::AtomicStoreRelease(s_swapRequested
, FALSE
);
323 // Run from the graphics thread (from Fifo.cpp)
324 void VideoFifo_CheckSwapRequestAt(u32 xfbAddr
, u32 fbWidth
, u32 fbHeight
)
326 if (g_ActiveConfig
.bUseXFB
)
328 if(Common::AtomicLoadAcquire(s_swapRequested
))
330 u32 aLower
= xfbAddr
;
331 u32 aUpper
= xfbAddr
+ 2 * fbWidth
* fbHeight
;
332 u32 bLower
= s_beginFieldArgs
.xfbAddr
;
333 u32 bUpper
= s_beginFieldArgs
.xfbAddr
+ 2 * s_beginFieldArgs
.fbWidth
* s_beginFieldArgs
.fbHeight
;
335 if (addrRangesOverlap(aLower
, aUpper
, bLower
, bUpper
))
336 VideoFifo_CheckSwapRequest();
341 // Run from the CPU thread (from VideoInterface.cpp)
342 void Video_BeginField(u32 xfbAddr
, FieldType field
, u32 fbWidth
, u32 fbHeight
)
344 if (s_PluginInitialized
&& g_ActiveConfig
.bUseXFB
)
346 if (g_VideoInitialize
.bOnThread
)
348 while (Common::AtomicLoadAcquire(s_swapRequested
) && !s_FifoShuttingDown
)
349 //Common::SleepCurrentThread(1);
353 VideoFifo_CheckSwapRequest();
354 s_beginFieldArgs
.xfbAddr
= xfbAddr
;
355 s_beginFieldArgs
.field
= field
;
356 s_beginFieldArgs
.fbWidth
= fbWidth
;
357 s_beginFieldArgs
.fbHeight
= fbHeight
;
359 Common::AtomicStoreRelease(s_swapRequested
, TRUE
);
363 void Video_EndField()
367 void Video_AddMessage(const char* pstr
, u32 milliseconds
)
369 OSD::AddMessage(pstr
, milliseconds
);
372 void Video_Screenshot(const char* _szFilename
)
374 Renderer::SetScreenshot(_szFilename
);
385 static u32 s_AccessEFBResult
= 0;
387 void VideoFifo_CheckEFBAccess()
389 if (Common::AtomicLoadAcquire(s_efbAccessRequested
))
391 s_AccessEFBResult
= Renderer::AccessEFB(s_accessEFBArgs
.type
, s_accessEFBArgs
.x
, s_accessEFBArgs
.y
);
393 Common::AtomicStoreRelease(s_efbAccessRequested
, FALSE
);
397 u32
Video_AccessEFB(EFBAccessType type
, u32 x
, u32 y
, u32 InputData
)
399 if (s_PluginInitialized
)
401 s_accessEFBArgs
.type
= type
;
402 s_accessEFBArgs
.x
= x
;
403 s_accessEFBArgs
.y
= y
;
404 s_accessEFBArgs
.Data
= InputData
;
405 Common::AtomicStoreRelease(s_efbAccessRequested
, TRUE
);
407 if (g_VideoInitialize
.bOnThread
)
409 while (Common::AtomicLoadAcquire(s_efbAccessRequested
) && !s_FifoShuttingDown
)
410 //Common::SleepCurrentThread(1);
414 VideoFifo_CheckEFBAccess();
416 return s_AccessEFBResult
;
422 void Video_CommandProcessorRead16(u16
& _rReturnValue
, const u32 _Address
)
424 CommandProcessor::Read16(_rReturnValue
, _Address
);
427 void Video_CommandProcessorWrite16(const u16 _Data
, const u32 _Address
)
429 CommandProcessor::Write16(_Data
, _Address
);
432 void Video_PixelEngineRead16(u16
& _rReturnValue
, const u32 _Address
)
434 PixelEngine::Read16(_rReturnValue
, _Address
);
437 void Video_PixelEngineWrite16(const u16 _Data
, const u32 _Address
)
439 PixelEngine::Write16(_Data
, _Address
);
442 void Video_PixelEngineWrite32(const u32 _Data
, const u32 _Address
)
444 PixelEngine::Write32(_Data
, _Address
);
447 inline void Video_GatherPipeBursted(void)
449 CommandProcessor::GatherPipeBursted();
452 void Video_WaitForFrameFinish(void)
454 CommandProcessor::WaitForFrameFinish();
457 bool Video_IsFifoBusy(void)
459 return CommandProcessor::isFifoBusy
;