Move fullscreen display resolution control to the GUI with the rest of the fullscreen...
[dolphin.git] / Source / Plugins / Plugin_VideoOGL / Src / main.cpp
blob80607bfdfbc44c1e28485196f006f4e3460db58b
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 "LogManager.h"
54 #include "Thread.h"
55 #include "Atomic.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 GFXDebuggerOGL *m_DebuggerFrame = NULL;
68 #endif // HAVE_WX
70 #include "VideoConfig.h"
71 #include "LookUpTables.h"
72 #include "ImageWrite.h"
73 #include "Render.h"
74 #include "GLUtil.h"
75 #include "Fifo.h"
76 #include "OpcodeDecoding.h"
77 #include "TextureMngr.h"
78 #include "BPStructs.h"
79 #include "VertexLoader.h"
80 #include "VertexLoaderManager.h"
81 #include "VertexManager.h"
82 #include "PixelShaderCache.h"
83 #include "PixelShaderManager.h"
84 #include "VertexShaderCache.h"
85 #include "VertexShaderManager.h"
86 #include "XFB.h"
87 #include "XFBConvert.h"
88 #include "CommandProcessor.h"
89 #include "PixelEngine.h"
90 #include "TextureConverter.h"
91 #include "PostProcessing.h"
92 #include "OnScreenDisplay.h"
93 #include "Setup.h"
94 #include "DLCache.h"
96 #include "VideoState.h"
98 #if defined(HAVE_COCOA) && HAVE_COCOA
99 #include <Cocoa/Cocoa.h>
100 #endif
102 SVideoInitialize g_VideoInitialize;
103 PLUGIN_GLOBALS* globals = NULL;
105 // Logging
106 int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
108 static bool s_PluginInitialized = false;
110 volatile u32 s_swapRequested = FALSE;
111 static u32 s_efbAccessRequested = FALSE;
112 static volatile u32 s_FifoShuttingDown = FALSE;
113 static bool ForceSwap = true;
115 bool IsD3D()
117 return false;
120 void GetDllInfo (PLUGIN_INFO* _PluginInfo)
122 _PluginInfo->Version = 0x0100;
123 _PluginInfo->Type = PLUGIN_TYPE_VIDEO;
124 #ifdef DEBUGFAST
125 sprintf(_PluginInfo->Name, "Dolphin OpenGL (DebugFast)");
126 #elif defined _DEBUG
127 sprintf(_PluginInfo->Name, "Dolphin OpenGL (Debug)");
128 #else
129 sprintf(_PluginInfo->Name, "Dolphin OpenGL");
130 #endif
133 void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
135 globals = _pPluginGlobals;
136 LogManager::SetInstance((LogManager *)globals->logManager);
139 // This is used for the functions right below here which use wxwidgets
140 #if defined(HAVE_WX) && HAVE_WX
141 #ifdef _WIN32
142 WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
143 extern HINSTANCE g_hInstance;
144 #endif
146 wxWindow* GetParentedWxWindow(HWND Parent)
148 #ifdef _WIN32
149 wxSetInstance((HINSTANCE)g_hInstance);
150 #endif
151 wxWindow *win = new wxWindow();
152 #ifdef _WIN32
153 win->SetHWND((WXHWND)Parent);
154 win->AdoptAttributesFromHWND();
155 #endif
156 return win;
158 #endif
160 void DllDebugger(HWND _hParent, bool Show)
162 #if defined(HAVE_WX) && HAVE_WX
163 if (Show) {
164 if (!m_DebuggerFrame)
165 m_DebuggerFrame = new GFXDebuggerOGL(NULL);
166 m_DebuggerFrame->Show();
167 } else {
168 if (m_DebuggerFrame) m_DebuggerFrame->Hide();
170 #endif
173 void DllConfig(HWND _hParent)
175 g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
176 g_Config.GameIniLoad(globals->game_ini);
177 g_Config.UpdateProjectionHack();
178 UpdateActiveConfig();
179 #if defined(HAVE_WX) && HAVE_WX
180 wxWindow *frame = GetParentedWxWindow(_hParent);
181 m_ConfigFrame = new GFXConfigDialogOGL(frame);
183 // Prevent user to show more than 1 config window at same time
184 #ifdef _WIN32
185 frame->Disable();
186 m_ConfigFrame->CreateGUIControls();
187 m_ConfigFrame->ShowModal();
188 frame->Enable();
189 #else
190 m_ConfigFrame->CreateGUIControls();
191 m_ConfigFrame->ShowModal();
192 #endif
194 #ifdef _WIN32
195 frame->SetFocus();
196 frame->SetHWND(NULL);
197 #endif
199 m_ConfigFrame->Destroy();
200 m_ConfigFrame = NULL;
201 frame->Destroy();
202 #endif
205 void Initialize(void *init)
207 frameCount = 0;
208 SVideoInitialize *_pVideoInitialize = (SVideoInitialize*)init;
209 // Create a shortcut to _pVideoInitialize that can also update it
210 g_VideoInitialize = *(_pVideoInitialize);
211 InitXFBConvTables();
213 g_Config.Load((std::string(File::GetUserPath(D_CONFIG_IDX)) + "gfx_opengl.ini").c_str());
214 g_Config.GameIniLoad(globals->game_ini);
216 g_Config.UpdateProjectionHack();
217 #if defined(HAVE_WX) && HAVE_WX
218 //Enable support for PNG screenshots.
219 wxImage::AddHandler( new wxPNGHandler );
220 #endif
221 UpdateActiveConfig();
223 if (!OpenGL_Create(g_VideoInitialize, 640, 480))
225 g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
226 return;
229 _pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
230 _pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
232 // Now the window handle is written
233 _pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
234 #if defined(HAVE_X11) && HAVE_X11
235 _pVideoInitialize->pXWindow = g_VideoInitialize.pXWindow;
236 #endif
238 OSD::AddMessage("Dolphin OpenGL Video Plugin" ,5000);
241 void DoState(unsigned char **ptr, int mode) {
242 #if defined(HAVE_X11) && HAVE_X11
243 OpenGL_MakeCurrent();
244 #endif
245 // Clear all caches that touch RAM
246 TextureMngr::Invalidate(false);
247 VertexLoaderManager::MarkAllDirty();
249 PointerWrap p(ptr, mode);
250 VideoCommon_DoState(p);
252 // Refresh state.
253 if (mode == PointerWrap::MODE_READ)
255 BPReload();
256 RecomputeCachedArraybases();
260 void EmuStateChange(PLUGIN_EMUSTATE newState)
262 Fifo_RunLoop((newState == PLUGIN_EMUSTATE_PLAY) ? true : false);
265 // This is called after Video_Initialize() from the Core
266 void Video_Prepare(void)
268 OpenGL_MakeCurrent();
269 if (!Renderer::Init()) {
270 g_VideoInitialize.pLog("Renderer::Create failed\n", TRUE);
271 PanicAlert("Can't create opengl renderer. You might be missing some required opengl extensions, check the logs for more info");
272 exit(1);
275 s_swapRequested = FALSE;
276 s_efbAccessRequested = FALSE;
277 s_FifoShuttingDown = FALSE;
279 CommandProcessor::Init();
280 PixelEngine::Init();
282 TextureMngr::Init();
284 BPInit();
285 VertexManager::Init();
286 Fifo_Init(); // must be done before OpcodeDecoder_Init()
287 OpcodeDecoder_Init();
288 VertexShaderCache::Init();
289 VertexShaderManager::Init();
290 PixelShaderCache::Init();
291 PixelShaderManager::Init();
292 PostProcessing::Init();
293 GL_REPORT_ERRORD();
294 VertexLoaderManager::Init();
295 TextureConverter::Init();
296 DLCache::Init();
298 // Notify the core that the video plugin is ready
299 g_VideoInitialize.pCoreMessage(WM_USER_CREATE);
301 s_PluginInitialized = true;
302 INFO_LOG(VIDEO, "Video plugin initialized.");
305 void Shutdown(void)
307 s_PluginInitialized = false;
308 ForceSwap = true;
310 s_efbAccessRequested = FALSE;
311 s_swapRequested = FALSE;
312 s_FifoShuttingDown = FALSE;
314 DLCache::Shutdown();
315 Fifo_Shutdown();
316 PostProcessing::Shutdown();
318 // The following calls are NOT Thread Safe
319 // And need to be called from the video thread
320 TextureConverter::Shutdown();
321 VertexLoaderManager::Shutdown();
322 VertexShaderCache::Shutdown();
323 VertexShaderManager::Shutdown();
324 PixelShaderManager::Shutdown();
325 PixelShaderCache::Shutdown();
326 VertexManager::Shutdown();
327 TextureMngr::Shutdown();
328 OpcodeDecoder_Shutdown();
329 Renderer::Shutdown();
330 OpenGL_Shutdown();
333 // Enter and exit the video loop
334 void Video_EnterLoop()
336 Fifo_EnterLoop(g_VideoInitialize);
339 void Video_ExitLoop()
341 Fifo_ExitLoop();
343 s_FifoShuttingDown = TRUE;
346 // Screenshot and screen message
348 void Video_Screenshot(const char *_szFilename)
350 Renderer::SetScreenshot(_szFilename);
353 void Video_AddMessage(const char* pstr, u32 milliseconds)
355 OSD::AddMessage(pstr, milliseconds);
358 void Video_SetRendering(bool bEnabled) {
359 Fifo_SetRendering(bEnabled);
362 static volatile struct
364 u32 xfbAddr;
365 FieldType field;
366 u32 fbWidth;
367 u32 fbHeight;
368 } s_beginFieldArgs;
370 // Run from the graphics thread (from Fifo.cpp)
371 void VideoFifo_CheckSwapRequest()
373 if (Common::AtomicLoadAcquire(s_swapRequested))
375 if (ForceSwap || g_ActiveConfig.bUseXFB)
377 Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
380 Common::AtomicStoreRelease(s_swapRequested, FALSE);
384 inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
386 return !((aLower >= bUpper) || (bLower >= aUpper));
389 // Run from the graphics thread (from Fifo.cpp)
390 void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
392 if (Common::AtomicLoadAcquire(s_swapRequested) && g_ActiveConfig.bUseXFB)
394 u32 aLower = xfbAddr;
395 u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
396 u32 bLower = s_beginFieldArgs.xfbAddr;
397 u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbWidth * s_beginFieldArgs.fbHeight;
399 if (addrRangesOverlap(aLower, aUpper, bLower, bUpper))
400 VideoFifo_CheckSwapRequest();
403 ForceSwap = false;
406 // Run from the CPU thread (from VideoInterface.cpp)
407 void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
409 if (s_PluginInitialized && g_ActiveConfig.bUseXFB)
411 s_beginFieldArgs.xfbAddr = xfbAddr;
412 s_beginFieldArgs.field = field;
413 s_beginFieldArgs.fbWidth = fbWidth;
414 s_beginFieldArgs.fbHeight = fbHeight;
416 Common::AtomicStoreRelease(s_swapRequested, TRUE);
417 if (g_VideoInitialize.bOnThread)
419 while (Common::AtomicLoadAcquire(s_swapRequested) && !s_FifoShuttingDown)
420 //Common::SleepCurrentThread(1);
421 Common::YieldCPU();
423 else
424 VideoFifo_CheckSwapRequest();
428 // Run from the CPU thread (from VideoInterface.cpp)
429 void Video_EndField()
433 static struct
435 EFBAccessType type;
436 u32 x;
437 u32 y;
438 } s_accessEFBArgs;
440 static u32 s_AccessEFBResult = 0;
442 void VideoFifo_CheckEFBAccess()
444 if (Common::AtomicLoadAcquire(s_efbAccessRequested))
446 s_AccessEFBResult = Renderer::AccessEFB(s_accessEFBArgs.type, s_accessEFBArgs.x, s_accessEFBArgs.y);
448 Common::AtomicStoreRelease(s_efbAccessRequested, FALSE);
452 u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
454 if (s_PluginInitialized)
456 s_accessEFBArgs.type = type;
457 s_accessEFBArgs.x = x;
458 s_accessEFBArgs.y = y;
460 Common::AtomicStoreRelease(s_efbAccessRequested, TRUE);
462 if (g_VideoInitialize.bOnThread)
464 while (Common::AtomicLoadAcquire(s_efbAccessRequested) && !s_FifoShuttingDown)
465 //Common::SleepCurrentThread(1);
466 Common::YieldCPU();
468 else
469 VideoFifo_CheckEFBAccess();
471 return s_AccessEFBResult;
474 return 0;
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();