Merged identical VertexManager code from DX9/DX11/OGL plugins into VideoCommon. Still...
[dolphin.git] / Source / Plugins / Plugin_VideoOGL / Src / main.cpp
blob94d4531a62fd575008d8a41389ae4a8f80b938dd
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/
20 // OpenGL Plugin Documentation
21 /*
23 1.1 Display settings
25 Internal and fullscreen resolution: Since the only internal resolutions allowed
26 are also fullscreen resolution allowed by the system there is only need for one
27 resolution setting that applies to both the internal resolution and the
28 fullscreen resolution. - Apparently no, someone else doesn't agree
30 Todo: Make the internal resolution option apply instantly, currently only the
31 native and 2x option applies instantly. To do this we need to be able to change
32 the reinitialize FramebufferManager:Init() while a game is running.
34 1.2 Screenshots
37 The screenshots should be taken from the internal representation of the picture
38 regardless of what the current window size is. Since AA and wireframe is
39 applied together with the picture resizing this rule is not currently applied
40 to AA or wireframe pictures, they are instead taken from whatever the window
41 size is.
43 Todo: Render AA and wireframe to a separate picture used for the screenshot in
44 addition to the one for display.
46 1.3 AA
48 Make AA apply instantly during gameplay if possible
52 #include "Globals.h"
53 #include "Atomic.h"
54 #include "Thread.h"
55 #include "LogManager.h"
57 #include <cstdarg>
59 #ifdef _WIN32
60 #include "OS/Win32.h"
61 #endif
63 #if defined(HAVE_WX) && HAVE_WX
64 #include "GUI/ConfigDlg.h"
65 GFXConfigDialogOGL *m_ConfigFrame = NULL;
66 #include "Debugger/Debugger.h"
67 #endif // HAVE_WX
69 #include "VideoConfig.h"
70 #include "LookUpTables.h"
71 #include "ImageWrite.h"
72 #include "Render.h"
73 #include "GLUtil.h"
74 #include "Fifo.h"
75 #include "OpcodeDecoding.h"
76 #include "TextureCache.h"
77 #include "BPStructs.h"
78 #include "VertexLoader.h"
79 #include "VertexLoaderManager.h"
80 #include "VertexManager.h"
81 #include "PixelShaderCache.h"
82 #include "PixelShaderManager.h"
83 #include "VertexShaderCache.h"
84 #include "VertexShaderManager.h"
85 #include "XFB.h"
86 #include "XFBConvert.h"
87 #include "CommandProcessor.h"
88 #include "PixelEngine.h"
89 #include "TextureConverter.h"
90 #include "PostProcessing.h"
91 #include "OnScreenDisplay.h"
92 #include "Setup.h"
93 #include "DLCache.h"
95 #include "VideoState.h"
97 SVideoInitialize g_VideoInitialize;
98 PLUGIN_GLOBALS* globals = NULL;
100 // Logging
101 int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
103 static bool s_PluginInitialized = false;
105 volatile u32 s_swapRequested = FALSE;
106 #if defined(HAVE_X11) && HAVE_X11
107 static volatile u32 s_doStateRequested = FALSE;
108 #endif
109 static u32 s_efbAccessRequested = FALSE;
110 static volatile u32 s_FifoShuttingDown = FALSE;
112 static volatile struct
114 u32 xfbAddr;
115 FieldType field;
116 u32 fbWidth;
117 u32 fbHeight;
118 } s_beginFieldArgs;
120 static volatile EFBAccessType s_AccessEFBType;
122 bool IsD3D()
124 return false;
127 // This is used for the functions right below here which use wxwidgets
128 #if defined(HAVE_WX) && HAVE_WX
129 #ifdef _WIN32
130 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
131 extern HINSTANCE g_hInstance;
132 #endif
133 #endif
135 void GetDllInfo(PLUGIN_INFO* _PluginInfo)
137 _PluginInfo->Version = 0x0100;
138 _PluginInfo->Type = PLUGIN_TYPE_VIDEO;
139 #ifdef DEBUGFAST
140 sprintf(_PluginInfo->Name, "Dolphin OpenGL (DebugFast)");
141 #elif defined _DEBUG
142 sprintf(_PluginInfo->Name, "Dolphin OpenGL (Debug)");
143 #else
144 sprintf(_PluginInfo->Name, "Dolphin OpenGL");
145 #endif
148 void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
150 globals = _pPluginGlobals;
151 LogManager::SetInstance((LogManager*)globals->logManager);
154 void *DllDebugger(void *_hParent, bool Show)
156 #if defined(HAVE_WX) && HAVE_WX
157 return new GFXDebuggerOGL((wxWindow *)_hParent);
158 #else
159 return NULL;
160 #endif
163 void DllConfig(void *_hParent)
165 g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
166 g_Config.GameIniLoad(globals->game_ini);
167 g_Config.UpdateProjectionHack();
168 UpdateActiveConfig();
169 #if defined(HAVE_WX) && HAVE_WX
170 m_ConfigFrame = new GFXConfigDialogOGL((wxWindow *)_hParent);
172 m_ConfigFrame->CreateGUIControls();
173 m_ConfigFrame->ShowModal();
174 m_ConfigFrame->Destroy();
175 #endif
178 void Initialize(void *init)
180 frameCount = 0;
181 SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
182 // Create a shortcut to _pVideoInitialize that can also update it
183 g_VideoInitialize = *(_pVideoInitialize);
184 InitXFBConvTables();
186 g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
187 g_Config.GameIniLoad(globals->game_ini);
189 g_Config.UpdateProjectionHack();
190 UpdateActiveConfig();
192 if (!OpenGL_Create(g_VideoInitialize, 640, 480))
194 g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
195 return;
198 _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
199 _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
201 // Now the window handle is written
202 _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
204 OSD::AddMessage("Dolphin OpenGL Video Plugin.", 5000);
205 s_PluginInitialized = true;
208 // This is called after Initialize() from the Core
209 // Run from the graphics thread
210 void Video_Prepare()
212 OpenGL_MakeCurrent();
213 if (!Renderer::Init()) {
214 g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
215 PanicAlert("Can't create opengl renderer. You might be missing some required opengl extensions, check the logs for more info");
216 exit(1);
219 s_efbAccessRequested = FALSE;
220 s_FifoShuttingDown = FALSE;
221 s_swapRequested = FALSE;
223 CommandProcessor::Init();
224 PixelEngine::Init();
226 TextureCache::Init();
228 BPInit();
229 g_vertex_manager = new OGL::VertexManager;
230 Fifo_Init(); // must be done before OpcodeDecoder_Init()
231 OpcodeDecoder_Init();
232 VertexShaderCache::Init();
233 VertexShaderManager::Init();
234 PixelShaderCache::Init();
235 PixelShaderManager::Init();
236 PostProcessing::Init();
237 GL_REPORT_ERRORD();
238 VertexLoaderManager::Init();
239 TextureConverter::Init();
240 DLCache::Init();
242 // Notify the core that the video plugin is ready
243 g_VideoInitialize.pCoreMessage(WM_USER_CREATE);
245 s_PluginInitialized = true;
246 INFO_LOG(VIDEO, "Video plugin initialized.");
250 void Shutdown()
252 s_PluginInitialized = false;
254 s_efbAccessRequested = FALSE;
255 s_FifoShuttingDown = FALSE;
256 s_swapRequested = FALSE;
257 DLCache::Shutdown();
258 Fifo_Shutdown();
259 PostProcessing::Shutdown();
261 // The following calls are NOT Thread Safe
262 // And need to be called from the video thread
263 TextureConverter::Shutdown();
264 VertexLoaderManager::Shutdown();
265 VertexShaderCache::Shutdown();
266 VertexShaderManager::Shutdown();
267 PixelShaderManager::Shutdown();
268 PixelShaderCache::Shutdown();
269 delete g_vertex_manager;
270 TextureCache::Shutdown();
271 OpcodeDecoder_Shutdown();
272 Renderer::Shutdown();
273 OpenGL_Shutdown();
276 static volatile struct
278 unsigned char **ptr;
279 int mode;
280 } s_doStateArgs;
282 // Run from the GPU thread on X11, CPU thread on the rest
283 static void check_DoState() {
284 #if defined(HAVE_X11) && HAVE_X11
285 if (Common::AtomicLoadAcquire(s_doStateRequested))
287 #endif
288 // Clear all caches that touch RAM
289 TextureCache::Invalidate(false);
290 VertexLoaderManager::MarkAllDirty();
292 PointerWrap p(s_doStateArgs.ptr, s_doStateArgs.mode);
293 VideoCommon_DoState(p);
295 // Refresh state.
296 if (s_doStateArgs.mode == PointerWrap::MODE_READ)
298 BPReload();
299 RecomputeCachedArraybases();
302 #if defined(HAVE_X11) && HAVE_X11
303 Common::AtomicStoreRelease(s_doStateRequested, FALSE);
305 #endif
308 // Run from the CPU thread
309 void DoState(unsigned char **ptr, int mode)
311 s_doStateArgs.ptr = ptr;
312 s_doStateArgs.mode = mode;
313 #if defined(HAVE_X11) && HAVE_X11
314 Common::AtomicStoreRelease(s_doStateRequested, TRUE);
315 if (g_VideoInitialize.bOnThread)
317 while (Common::AtomicLoadAcquire(s_doStateRequested) && !s_FifoShuttingDown)
318 //Common::SleepCurrentThread(1);
319 Common::YieldCPU();
321 else
322 #endif
323 check_DoState();
326 void EmuStateChange(PLUGIN_EMUSTATE newState)
328 Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
331 // Enter and exit the video loop
332 void Video_EnterLoop()
334 Fifo_EnterLoop(g_VideoInitialize);
337 void Video_ExitLoop()
339 Fifo_ExitLoop();
340 s_FifoShuttingDown = TRUE;
343 void Video_SetRendering(bool bEnabled)
345 Fifo_SetRendering(bEnabled);
348 // Run from the graphics thread (from Fifo.cpp)
349 void VideoFifo_CheckSwapRequest()
351 if(g_ActiveConfig.bUseXFB)
353 if (Common::AtomicLoadAcquire(s_swapRequested))
355 EFBRectangle rc;
356 Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight,rc);
357 Common::AtomicStoreRelease(s_swapRequested, FALSE);
362 static inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
364 return !((aLower >= bUpper) || (bLower >= aUpper));
367 // Run from the graphics thread (from Fifo.cpp)
368 void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
370 if (g_ActiveConfig.bUseXFB)
372 if(Common::AtomicLoadAcquire(s_swapRequested))
374 u32 aLower = xfbAddr;
375 u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
376 u32 bLower = s_beginFieldArgs.xfbAddr;
377 u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbWidth * s_beginFieldArgs.fbHeight;
379 if (addrRangesOverlap(aLower, aUpper, bLower, bUpper))
380 VideoFifo_CheckSwapRequest();
385 // Run from the CPU thread (from VideoInterface.cpp)
386 void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
388 if (s_PluginInitialized && g_ActiveConfig.bUseXFB)
390 if (g_VideoInitialize.bOnThread)
392 while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown)
393 //Common::SleepCurrentThread(1);
394 Common::YieldCPU();
396 else
397 VideoFifo_CheckSwapRequest();
398 s_beginFieldArgs.xfbAddr = xfbAddr;
399 s_beginFieldArgs.field = field;
400 s_beginFieldArgs.fbWidth = fbWidth;
401 s_beginFieldArgs.fbHeight = fbHeight;
403 Common::AtomicStoreRelease(s_swapRequested, TRUE);
407 // Run from the CPU thread (from VideoInterface.cpp)
408 void Video_EndField()
412 void Video_AddMessage(const char* pstr, u32 milliseconds)
414 OSD::AddMessage(pstr, milliseconds);
417 // Screenshot
418 void Video_Screenshot(const char *_szFilename)
420 Renderer::SetScreenshot(_szFilename);
423 static struct
425 EFBAccessType type;
426 u32 x;
427 u32 y;
428 u32 Data;
429 } s_accessEFBArgs;
431 static u32 s_AccessEFBResult = 0;
433 void VideoFifo_CheckEFBAccess()
435 if (Common::AtomicLoadAcquire(s_efbAccessRequested))
437 s_AccessEFBResult = Renderer::AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y);
439 Common::AtomicStoreRelease(s_efbAccessRequested, FALSE);
443 u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
445 if (s_PluginInitialized)
447 s_accessEFBArgs.type = type;
448 s_accessEFBArgs.x = x;
449 s_accessEFBArgs.y = y;
450 s_accessEFBArgs.Data = InputData;
452 Common::AtomicStoreRelease(s_efbAccessRequested, TRUE);
454 if (g_VideoInitialize.bOnThread)
456 while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown)
457 //Common::SleepCurrentThread(1);
458 Common::YieldCPU();
460 else
461 VideoFifo_CheckEFBAccess();
463 return s_AccessEFBResult;
466 return 0;
469 void VideoFifo_CheckAsyncRequest() {
470 VideoFifo_CheckSwapRequest();
471 VideoFifo_CheckEFBAccess();
472 #if defined(HAVE_X11) && HAVE_X11
473 check_DoState();
474 #endif
477 void Video_CommandProcessorRead16(u16& _rReturnValue, const u32 _Address)
479 CommandProcessor::Read16(_rReturnValue, _Address);
482 void Video_CommandProcessorWrite16(const u16 _Data, const u32 _Address)
484 CommandProcessor::Write16(_Data, _Address);
487 void Video_PixelEngineRead16(u16& _rReturnValue, const u32 _Address)
489 PixelEngine::Read16(_rReturnValue, _Address);
492 void Video_PixelEngineWrite16(const u16 _Data, const u32 _Address)
494 PixelEngine::Write16(_Data, _Address);
497 void Video_PixelEngineWrite32(const u32 _Data, const u32 _Address)
499 PixelEngine::Write32(_Data, _Address);
502 void Video_GatherPipeBursted(void)
504 CommandProcessor::GatherPipeBursted();
507 void Video_WaitForFrameFinish(void)
509 CommandProcessor::WaitForFrameFinish();
512 bool Video_IsFifoBusy(void)
514 return CommandProcessor::isFifoBusy;
517 void Video_AbortFrame(void)
519 CommandProcessor::AbortFrame();