diff options
Diffstat (limited to 'Source')
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp | 3 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp | 57 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h | 1 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp | 2 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/Globals.h | 1 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 14 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/main.cpp | 28 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/resource.h | 2 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/resource.rc | 15 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoOGL/Src/Render.cpp | 1642 | ||||
| -rw-r--r-- | Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp | 4 |
11 files changed, 910 insertions, 859 deletions
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp index cb07d9d828..f9217cfc92 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp @@ -62,6 +62,7 @@ struct TabDirect3D : public W32Util::Tab CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
+ CheckDlgButton(hDlg, IDC_RENDER_IN_MAINWINDOW, g_Config.renderInMainframe ? TRUE : FALSE);
}
void Command(HWND hDlg,WPARAM wParam)
@@ -83,6 +84,8 @@ struct TabDirect3D : public W32Util::Tab g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
+ g_Config.renderInMainframe = Button_GetCheck(GetDlgItem(hDlg, IDC_RENDER_IN_MAINWINDOW)) ? true : false;
+ g_Config.Save();
}
};
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp b/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp index 9008c16002..270f494b98 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp @@ -6,17 +6,23 @@ namespace EmuWindow
{
- HWND m_hWnd;
- HINSTANCE m_hInstance;
+ HWND m_hWnd = NULL;
+ HWND m_hParent = NULL;
+ HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = "DolphinEmuWnd";
+ int g_winstyle;
HWND GetWnd()
{
-
return m_hWnd;
}
+ HWND GetParentWnd()
+ {
+ return m_hParent;
+ }
+
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
@@ -80,23 +86,42 @@ namespace EmuWindow m_hInstance = hInstance;
RegisterClassEx( &wndClass );
- DWORD style = windowed ? WS_OVERLAPPEDWINDOW : WS_POPUP;
+ if (parent && windowed)
+ {
+ m_hWnd = CreateWindow(m_szClassName, title,
+ WS_CHILD,
+ CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
+ parent, NULL, hInstance, NULL );
- RECT rc = {0, 0, width, height};
- AdjustWindowRect(&rc, style, false);
+ m_hParent = parent;
- int w = rc.right - rc.left;
- int h = rc.bottom - rc.top;
+ ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
+ }
+ else
+ {
+ DWORD style = windowed ? WS_OVERLAPPEDWINDOW : WS_POPUP;
- rc.left = (1280 - w)/2;
- rc.right = rc.left + w;
- rc.top = (1024 - h)/2;
- rc.bottom = rc.top + h;
+ RECT rc = {0, 0, width, height};
+ AdjustWindowRect(&rc, style, false);
+
+ int w = rc.right - rc.left;
+ int h = rc.bottom - rc.top;
- m_hWnd = CreateWindow(m_szClassName, title,
- style,
- rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
- parent, NULL, hInstance, NULL );
+ rc.left = (1280 - w)/2;
+ rc.right = rc.left + w;
+ rc.top = (1024 - h)/2;
+ rc.bottom = rc.top + h;
+
+
+ m_hWnd = CreateWindow(m_szClassName, title,
+ style,
+ rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
+ parent, NULL, hInstance, NULL );
+
+ g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
+ g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
+
+ }
return m_hWnd;
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h b/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h index 8ca0281a7e..0746b17a5a 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h @@ -6,6 +6,7 @@ namespace EmuWindow
{
HWND GetWnd();
+ HWND GetParentWnd();
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title);
void Show();
void Close();
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp index c677c40d9c..db3ba9ffe5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp @@ -15,6 +15,7 @@ void Config::Load() iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
+ iniFile.Get("Hardware", "RenderInMainframe", &renderInMainframe, true);
iniFile.Get("Hardware", "VSync", &bVsync, 0);
if (iAdapter == -1)
iAdapter = 0;
@@ -40,6 +41,7 @@ void Config::Save() iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "VSync", bVsync);
+ iniFile.Set("Hardware", "RenderInMainframe", renderInMainframe);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Globals.h b/Source/Plugins/Plugin_VideoDX9/Src/Globals.h index eb3d74fd87..9800d90352 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Globals.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/Globals.h @@ -16,6 +16,7 @@ struct Config int iPostprocessEffect;
int iCompileDLsLevel;
+ bool renderInMainframe;
bool bFullscreen;
bool bVsync;
bool bWireFrame;
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index d3c98fc3ca..49bddb3ab3 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -100,6 +100,20 @@ void Renderer::ReinitView() void Renderer::SwapBuffers(void)
{
+ // center window again
+ if (EmuWindow::GetParentWnd())
+ {
+ RECT rcWindow;
+ GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
+
+ int width = rcWindow.right - rcWindow.left;
+ int height = rcWindow.bottom - rcWindow.top;
+
+ ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE);
+ // nBackbufferWidth = width;
+ // nBackbufferHeight = height;
+ }
+
//Finish up the current frame, print some stats
Postprocess::FinalizeFrame();
if (g_Config.bOverlayStats)
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp index e2aa195c4a..d03fde5d80 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/main.cpp @@ -66,25 +66,28 @@ void UpdateFPSDisplay(const char *text) bool Init()
{
+ g_Config.Load();
+
if (initCount==0)
{
// create the window
- // if( g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
+ if( !g_Config.renderInMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
{
- // create the window
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait...");
- if( g_VideoInitialize.pWindowHandle == NULL ) {
- MessageBox(GetActiveWindow(), "failed to create window", "Fatal Error", MB_OK);
- return false;
- }
-
- g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
- g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
- EmuWindow::Show();
}
+ else
+ {
+ g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait...");
+ }
- if( g_VideoInitialize.pPeekMessages == NULL )
- return false;
+ if( g_VideoInitialize.pWindowHandle == NULL ) {
+ MessageBox(GetActiveWindow(), "failed to create window", "Fatal Error", MB_OK);
+ return false;
+ }
+
+ EmuWindow::Show();
+ g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
+ g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
if (FAILED(D3D::Init()))
{
@@ -95,7 +98,6 @@ bool Init() }
initCount++;
- g_Config.Load();
return true;
}
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/resource.h b/Source/Plugins/Plugin_VideoDX9/Src/resource.h index 2a2450a031..4aac2298ff 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/resource.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/resource.h @@ -17,6 +17,8 @@ #define IDC_FULLSCREENENABLE2 1003
#define IDC_VSYNC 1003
#define IDC_DEBUGSTEP 1004
+#define IDC_VSYNC2 1004
+#define IDC_RENDER_IN_MAINWINDOW 1004
#define IDC_REGISTERS 1005
#define IDC_ENABLEDEBUGGING 1006
#define IDC_TAB1 1007
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/resource.rc b/Source/Plugins/Plugin_VideoDX9/Src/resource.rc index 1b3e6a7c8f..89e99262a9 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/resource.rc +++ b/Source/Plugins/Plugin_VideoDX9/Src/resource.rc @@ -81,16 +81,17 @@ FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN
LTEXT "&Graphics card:",IDC_STATIC,7,9,61,8
COMBOBOX IDC_ADAPTER,68,7,156,84,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "&Fullscreen video mode:",IDC_STATIC,7,55,74,8
- COMBOBOX IDC_RESOLUTION,87,54,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
- LTEXT "&Antialias mode:",IDC_STATIC,7,114,61,8
- COMBOBOX IDC_ANTIALIASMODE,68,113,156,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Fullscreen video mode:",IDC_STATIC,7,63,74,8
+ COMBOBOX IDC_RESOLUTION,87,62,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ LTEXT "&Antialias mode:",IDC_STATIC,7,122,61,8
+ COMBOBOX IDC_ANTIALIASMODE,68,121,156,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "&Rotate windowed mode 90 degrees (for Ikaruga)",IDC_CHECK1,
- "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_DISABLED | WS_TABSTOP,87,89,137,17
- LTEXT "&Windowed resolution:",IDC_STATIC,7,74,74,8
- COMBOBOX IDC_RESOLUTIONWINDOWED,87,73,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ "Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_DISABLED | WS_TABSTOP,87,97,137,17
+ LTEXT "&Windowed resolution:",IDC_STATIC,7,82,74,8
+ COMBOBOX IDC_RESOLUTIONWINDOWED,87,81,137,73,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
CONTROL "&Fullscreen",IDC_FULLSCREENENABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,25,141,8
CONTROL "&V-Sync",IDC_VSYNC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,38,141,8
+ CONTROL "&Render in main window",IDC_RENDER_IN_MAINWINDOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,50,141,8
END
IDD_DEBUGGER DIALOGEX 0, 0, 234, 254
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index 22a1035181..707b249590 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -15,824 +15,824 @@ // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#include "Globals.h" -#include <list> - -#include "GLInit.h" -#include "Render.h" -#include "OpcodeDecoding.h" -#include "BPStructs.h" -#include "TextureMngr.h" -#include "rasterfont.h" -#include "VertexShader.h" -#include "PixelShader.h" -#include "VertexLoader.h" - - -#ifdef _WIN32 -#include "EmuWindow.h" -#else -#endif - -struct MESSAGE -{ - MESSAGE() {} - MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } - char str[255]; - u32 dwTimeStamp; -}; - -CGcontext g_cgcontext; -CGprofile g_cgvProf, g_cgfProf; - -static int g_MaxTexWidth = 0, g_MaxTexHeight = 0; -static RasterFont* s_pfont = NULL; -static std::list<MESSAGE> s_listMsgs; -static bool s_bFullscreen = false; -static bool s_bOutputCgErrors = true; -static int nZBufferRender = 0; // if > 0, then using zbuffer render -static u32 s_uFramebuffer = 0; -static u32 s_RenderTargets[1] = {0}, s_DepthTarget = 0, s_ZBufferTarget = 0; -static bool s_bATIDrawBuffers = false, s_bHaveStencilBuffer = false; -static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal; -static int s_nCurTarget = 0; -bool g_bBlendLogicOp = false; - - -void HandleCgError(CGcontext ctx, CGerror err, void* appdata); - - -bool Renderer::Create2() -{ - bool bSuccess = true; - GLenum err = GL_NO_ERROR; - g_cgcontext = cgCreateContext(); - cgGetError(); - cgSetErrorHandler(HandleCgError, NULL); - - // fill the opengl extension map - const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); - if (ptoken == NULL) return false; - - __Log("Supported OpenGL Extensions:\n"); - __Log(ptoken); // write to the log file - __Log("\n"); - - if( strstr(ptoken, "GL_EXT_blend_logic_op") != NULL ) - g_bBlendLogicOp = true; - if( strstr(ptoken, "ATI_draw_buffers") != NULL ) - s_bATIDrawBuffers = true; - - s_bFullscreen = g_Config.bFullscreen; - - if (glewInit() != GLEW_OK) { - ERROR_LOG("glewInit() failed!\n"); - return false; - } - - if (!GLEW_EXT_framebuffer_object) { - ERROR_LOG("*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\n"); - bSuccess = false; - } - - if (!GLEW_EXT_secondary_color) { - ERROR_LOG("*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\n"); - bSuccess = false; - } - - int numvertexattribs=0; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs); - - if (numvertexattribs < 11) { - ERROR_LOG("*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\n", numvertexattribs); - bSuccess = false; - } - - if (!bSuccess) - return false; - -#ifdef _WIN32 - if (WGLEW_EXT_swap_control) - wglSwapIntervalEXT(0); - else - ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); -#else - if (glXSwapIntervalSGI) - glXSwapIntervalSGI(0); - else - ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); -#endif - - // check the max texture width and height - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth); - g_MaxTexHeight = g_MaxTexWidth; - - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) bSuccess = false; - - if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers) - glDrawBuffers = glDrawBuffersARB; - - glGenFramebuffersEXT( 1, &s_uFramebuffer); - if (s_uFramebuffer == 0) { - ERROR_LOG("failed to create the renderbuffer\n"); - } - - _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); - - // create the framebuffer targets - glGenTextures(ARRAYSIZE(s_RenderTargets), s_RenderTargets); - for(int i = 0; i < ARRAYSIZE(s_RenderTargets); ++i) { - glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[i]); - // initialize to default - glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if( glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERROR(); - } - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - s_nCurTarget = 0; - - GL_REPORT_ERROR(); - - int nMaxMRT = 0; - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxMRT); - - if( nMaxMRT > 1 ) { - // create zbuffer target - glGenTextures(1, &s_ZBufferTarget); - glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget); - glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if( glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); - GL_REPORT_ERROR(); - } - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - - // create the depth buffer - glGenRenderbuffersEXT( 1, &s_DepthTarget); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_nTargetWidth, s_nTargetHeight); - if( glGetError() != GL_NO_ERROR ) { - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, s_nTargetWidth, s_nTargetHeight); - s_bHaveStencilBuffer = false; - } - else s_bHaveStencilBuffer = true; - - GL_REPORT_ERROR(); - - // set as render targets - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget], 0 ); - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); - GL_REPORT_ERROR(); - - if( s_ZBufferTarget != 0 ) { - // test to make sure it works - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0); - bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT; - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0); - - if( bFailed ) { - glDeleteTextures(1, &s_ZBufferTarget); - s_ZBufferTarget = 0; - } - } - - if( s_ZBufferTarget == 0 ) - ERROR_LOG("disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT); - - //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); - - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - nZBufferRender = 0; - - GL_REPORT_ERROR(); - if (err != GL_NO_ERROR) bSuccess = false; - - s_pfont = new RasterFont(); - - SetAA(g_Config.aa); - GL_REPORT_ERROR(); - - // load the effect, find the best profiles (if any) - if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { - ERROR_LOG("arbvp1 not supported\n"); - return false; - } - if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { - ERROR_LOG("arbfp1 not supported\n"); - return false; - } - - g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX); - g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);//CG_PROFILE_ARBFP1; - //cgGLSetOptimalOptions(g_cgvProf); - //cgGLSetOptimalOptions(g_cgfProf); - - //ERROR_LOG("max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf)); - int nenvvertparams, nenvfragparams, naddrregisters[2]; - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &nenvvertparams); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &nenvfragparams); - glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &naddrregisters[0]); - glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &naddrregisters[1]); - __Log("max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams); - __Log("max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]); - - if( nenvvertparams < 238 ) - ERROR_LOG("not enough vertex shader environment constants!!\n"); - -#ifndef _DEBUG - cgGLSetDebugMode(GL_FALSE); -#endif - - if( cgGetError() != CG_NO_ERROR ) { - ERROR_LOG("cg error\n"); - return false; - } - - //glEnable(GL_POLYGON_OFFSET_FILL); - //glEnable(GL_POLYGON_OFFSET_LINE); - //glPolygonOffset(0, 1); - - if (!Initialize()) - return false; - - return glGetError() == GL_NO_ERROR && bSuccess; -} - -void Renderer::Shutdown(void) -{ - SAFE_DELETE(s_pfont); - - if( g_cgcontext != 0 ) { - cgDestroyContext(g_cgcontext); - g_cgcontext = 0; - } - - if( s_RenderTargets[0] ) { - glDeleteTextures(ARRAYSIZE(s_RenderTargets), s_RenderTargets); - memset(s_RenderTargets, 0, sizeof(s_RenderTargets)); - } - if( s_DepthTarget ) { - glDeleteRenderbuffersEXT(1, &s_DepthTarget); s_DepthTarget = 0; - } - - if (s_uFramebuffer != 0) { - glDeleteFramebuffersEXT( 1, &s_uFramebuffer); - s_uFramebuffer = 0; - } -} - - -bool Renderer::Initialize() -{ - glStencilFunc(GL_ALWAYS, 0, 0); - glBlendFunc(GL_ONE, GL_ONE); - - glViewport(0,0,s_nTargetWidth,s_nTargetWidth); // Reset The Current Viewport - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glShadeModel(GL_SMOOTH); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearDepth(1.0f); - glEnable(GL_DEPTH_TEST); - glDisable(GL_LIGHTING); - glDepthFunc(GL_LEQUAL); - - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // perspective correct interpolation of colors and tex coords - - // setup the default vertex declaration - glDisable(GL_STENCIL_TEST); - glEnable(GL_SCISSOR_TEST); - glScissor(0,0,nBackbufferWidth,nBackbufferHeight); - glBlendColorEXT(0, 0, 0, 0.5f); - glClearDepth(1.0f); - - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - //Renderer::SetZBufferRender(); - - // legacy multitexturing: select texture channel only - glActiveTexture(GL_TEXTURE0); - glClientActiveTexture(GL_TEXTURE0); - glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - - s_RenderMode = Renderer::RM_Normal; - - GLenum err = GL_NO_ERROR; - GL_REPORT_ERROR(); - return err == GL_NO_ERROR; -} - -void Renderer::AddMessage(const char* pstr, u32 ms) -{ - s_listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms)); -} - -void Renderer::ProcessMessages() -{ - if (s_listMsgs.size() > 0) { - int left = 25, top = 15; - list<MESSAGE>::iterator it = s_listMsgs.begin(); - - while( it != s_listMsgs.end() ) { - DrawText(it->str, left+1, top+1, 0xff000000); - DrawText(it->str, left, top, 0xffffff30); - top += 15; - - if ((int)(it->dwTimeStamp - timeGetTime()) < 0) - it = s_listMsgs.erase(it); - else ++it; - } - } -} - -void Renderer::DrawText(const char* pstr, int left, int top, u32 color) -{ - glColor3f(((color>>16) & 0xff)/255.0f, ((color>>8) & 0xff)/255.0f, (color & 0xff)/255.0f); - s_pfont->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0); -} - -void Renderer::SetAA(int aa) -{ - -} - -void Renderer::ReinitView(int nNewWidth, int nNewHeight) -{ - int oldscreen = s_bFullscreen; - - OpenGL_Shutdown(); - int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; - if (!OpenGL_Create(g_VideoInitialize, nNewWidth, nNewHeight)) {//nNewWidth&~7, nNewHeight&~7) ) { - ERROR_LOG("Failed to recreate, reverting to old settings\n"); - if (!OpenGL_Create(g_VideoInitialize, oldwidth, oldheight)) { - SysMessage("Failed to revert, exiting...\n"); - // TODO - don't takedown the entire emu - exit(0); - } - } - OpenGL_MakeCurrent(); - - if (oldscreen && !g_Config.bFullscreen) { // if transitioning from full screen -#ifdef _WIN32 - RECT rc; - rc.left = 0; rc.top = 0; - rc.right = nNewWidth; rc.bottom = nNewHeight; - AdjustWindowRect(&rc, EmuWindow::g_winstyle, FALSE); - - RECT rcdesktop; - GetWindowRect(GetDesktopWindow(), &rcdesktop); - - SetWindowLong( EmuWindow::GetWnd(), GWL_STYLE, EmuWindow::g_winstyle ); - SetWindowPos(EmuWindow::GetWnd(), HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2, - ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2, - rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); - UpdateWindow(EmuWindow::GetWnd()); -#else // linux -#endif - } - - nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; - nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; -} - -int Renderer::GetTargetWidth() -{ - return s_nTargetWidth; -} - -bool Renderer::CanBlendLogicOp() -{ - return g_bBlendLogicOp; -} - -int Renderer::GetTargetHeight() -{ - return s_nTargetHeight; -} - -void Renderer::SetRenderTarget(u32 targ) -{ - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, targ!=0?targ:s_RenderTargets[s_nCurTarget], 0 ); -} - -void Renderer::SetDepthTarget(u32 targ) -{ - glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targ != 0 ? targ : s_DepthTarget ); -} - -void Renderer::SetFramebuffer(u32 fb) -{ - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb != 0 ? fb : s_uFramebuffer ); -} - -u32 Renderer::GetRenderTarget() -{ - return s_RenderTargets[s_nCurTarget]; -} - -void Renderer::ResetGLState() -{ - glDisable(GL_SCISSOR_TEST); - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDepthMask(GL_FALSE); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - glDisable( GL_VERTEX_PROGRAM_ARB ); - glDisable( GL_FRAGMENT_PROGRAM_ARB ); -} - -void Renderer::RestoreGLState() -{ - glEnable(GL_SCISSOR_TEST); - - if (bpmem.genMode.cullmode>0) glEnable(GL_CULL_FACE); - if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST); - if (bpmem.blendmode.blendenable) glEnable(GL_BLEND); - if(bpmem.zmode.updateenable) glDepthMask(GL_TRUE); - - glEnable( GL_VERTEX_PROGRAM_ARB ); - glEnable( GL_FRAGMENT_PROGRAM_ARB ); - SetColorMask(); -} - -bool Renderer::IsUsingATIDrawBuffers() -{ - return s_bATIDrawBuffers; -} - -bool Renderer::HaveStencilBuffer() -{ - return s_bHaveStencilBuffer; -} - -void Renderer::SetZBufferRender() -{ - nZBufferRender = 10; // give it 10 frames - GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; - glDrawBuffers(2, s_drawbuffers); - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0); - _assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); -} - -void Renderer::FlushZBufferAlphaToTarget() -{ - ResetGLState(); - - SetRenderTarget(0); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - glViewport(0, 0, GetTargetWidth()<<g_AAx, GetTargetHeight()<<g_AAy); - - // texture map s_RenderTargets[s_curtarget] onto the main buffer - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget); - TextureMngr::EnableTexRECT(0); - // disable all other stages - for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - // setup the stencil to only accept pixels that have been written - glStencilFunc(GL_EQUAL, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(-1,-1); - glTexCoord2f(0, (float)(GetTargetHeight()<<g_AAy)); glVertex2f(-1,1); - glTexCoord2f((float)(GetTargetWidth()<<g_AAx), (float)(GetTargetWidth()<<g_AAy)); glVertex2f(1,1); - glTexCoord2f((float)(GetTargetWidth()<<g_AAx), 0); glVertex2f(1,-1); - glEnd(); - - GL_REPORT_ERRORD(); - - glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0); - RestoreGLState(); -} - -void Renderer::SetRenderMode(RenderMode mode) -{ - if( !s_bHaveStencilBuffer && mode == RM_ZBufferAlpha ) - mode = RM_ZBufferOnly; - - if( s_RenderMode == mode ) - return; - - if( mode == RM_Normal ) { - // flush buffers - if( s_RenderMode == RM_ZBufferAlpha ) { - FlushZBufferAlphaToTarget(); - glDisable(GL_STENCIL_TEST); - } - SetColorMask(); - SetRenderTarget(0); - SetZBufferRender(); - GL_REPORT_ERRORD(); - } - else if( s_RenderMode == RM_Normal ) { - // setup buffers - _assert_(GetZBufferTarget() && bpmem.zmode.updateenable); - - if( mode == RM_ZBufferAlpha ) { - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - } - - glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - GL_REPORT_ERRORD(); - } - else { - _assert_(GetZBufferTarget()); - _assert_(s_bHaveStencilBuffer); - - if( mode == RM_ZBufferOnly ) { - // flush and remove stencil - _assert_(s_RenderMode==RM_ZBufferAlpha); - FlushZBufferAlphaToTarget(); - glDisable(GL_STENCIL_TEST); - - SetRenderTarget(s_ZBufferTarget); - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - GL_REPORT_ERRORD(); - } - else { - _assert_(mode == RM_ZBufferAlpha&&s_RenderMode==RM_ZBufferOnly); - - // setup stencil - glEnable(GL_STENCIL_TEST); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_ALWAYS, 1, 0xff); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - } - } - - s_RenderMode = mode; -} - -Renderer::RenderMode Renderer::GetRenderMode() -{ - return s_RenderMode; -} - -u32 Renderer::GetZBufferTarget() -{ - return nZBufferRender > 0 ? s_ZBufferTarget : 0; -} - -void Renderer::Swap(const TRectangle& rc) -{ - OpenGL_Update(); // just updates the render window position and the backbuffer size - - DVProfileFunc _pf("Renderer::Swap"); - - Renderer::SetRenderMode(Renderer::RM_Normal); - - // render to the real buffer now - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer - glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); - - ResetGLState(); - - // texture map s_RenderTargets[s_curtarget] onto the main buffer - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget]); - TextureMngr::EnableTexRECT(0); - // disable all other stages - for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); - GL_REPORT_ERRORD(); - - - float FactorW = (float)s_nTargetWidth / (float)nBackbufferWidth; - float FactorH = (float)s_nTargetHeight / (float)nBackbufferHeight; - - float Max = (FactorW < FactorH) ? FactorH : FactorW; - float Temp = 1 / Max; - FactorW *= Temp; - FactorH *= Temp; - - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); glVertex2f(-FactorW,-FactorH); - glTexCoord2f(0, (float)s_nTargetHeight); glVertex2f(-FactorW,FactorH); - glTexCoord2f((float)s_nTargetWidth, (float)s_nTargetHeight); glVertex2f(FactorW,FactorH); - glTexCoord2f((float)s_nTargetWidth, 0); glVertex2f(FactorW,-FactorH); - glEnd(); - - glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0); - TextureMngr::DisableStage(0); - -// static int fpscount = 0; -// static float s_fps = 0; -// static u32 lasttime = timeGetTime(); -// -// if( ++fpscount >= 16 ) { -// s_fps = 16*1000.0f/(float)(timeGetTime() - lasttime); -// lasttime = timeGetTime(); -// fpscount = 0; -// } -// -// char strfps[25]; -// sprintf(strfps, "fps: %2.1f\n", s_fps); -// Renderer::DrawText(strfps, 20, 20, 0xFF00FFFF); - - if (g_Config.bOverlayStats) { - char st[2048]; - char *p = st; - p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); - p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive); - p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); - p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive); - p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); - p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive); - p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled); - p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated); - p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive); - p+=sprintf(p,"Num strip joins: %i\n",stats.numJoins); - p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims); - p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims); - p+=sprintf(p,"Num bad commands: %i%s\n",stats.thisFrame.numBadCommands,stats.thisFrame.numBadCommands?"!!!":""); - p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads); - p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); - p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads); - p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); - p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads); - p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); - - Renderer::DrawText(st, 20, 20, 0xFF00FFFF); - } - -#if defined(DVPROFILE) - if (g_bWriteProfile) { - //g_bWriteProfile = 0; - static int framenum = 0; - const int UPDATE_FRAMES = 8; - if (++framenum >= UPDATE_FRAMES) { - DVProfWrite("prof.txt", UPDATE_FRAMES); - DVProfClear(); - framenum = 0; - } - } -#endif - - // copy the rendered from to the real window - OpenGL_SwapBuffers(); - - GL_REPORT_ERRORD(); - - //clean out old stuff from caches - frameCount++; - PixelShaderMngr::Cleanup(); - TextureMngr::Cleanup(); - - // New frame - stats.ResetFrame(); - - glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); - -// s_nCurTarget = !s_nCurTarget; -// SetRenderTarget(0); - - if( nZBufferRender > 0 ) { - if( --nZBufferRender == 0 ) { - // turn off - nZBufferRender = 0; - glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); - glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0); - Renderer::SetRenderMode(RM_Normal); // turn off any zwrites - } - } - - RestoreGLState(); - GL_REPORT_ERRORD(); - - g_Config.iSaveTargetId = 0; - - // for testing zbuffer targets - //Renderer::SetZBufferRender(); - //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight()); -} - -bool Renderer::SaveRenderTarget(const char* filename, int jpeg) -{ - bool bflip = true; - vector<u32> data(s_nTargetWidth*s_nTargetHeight); - glReadPixels(0, 0, s_nTargetWidth, s_nTargetHeight, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); - if (glGetError() != GL_NO_ERROR) - return false; - - if (bflip) { - // swap scanlines - vector<u32> scanline(s_nTargetWidth); - for(u32 i = 0; i < s_nTargetHeight/2; ++i) { - memcpy(&scanline[0], &data[i*s_nTargetWidth], s_nTargetWidth*4); - memcpy(&data[i*s_nTargetWidth], &data[(s_nTargetHeight-i-1)*s_nTargetWidth], s_nTargetWidth*4); - memcpy(&data[(s_nTargetHeight-i-1)*s_nTargetWidth], &scanline[0], s_nTargetWidth*4); - } - } - - if (jpeg) return SaveJPEG(filename, s_nTargetWidth, s_nTargetHeight, &data[0], 70); - - return SaveTGA(filename, s_nTargetWidth, s_nTargetHeight, &data[0]); -} - -void Renderer::SetCgErrorOutput(bool bOutput) -{ - s_bOutputCgErrors = bOutput; -} - -void HandleGLError() -{ - const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); - if (pstr != NULL && pstr[0] != 0 ) { - GLint loc=0; - glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); - ERROR_LOG("program error at %d: ", loc); - ERROR_LOG((char*)pstr); - ERROR_LOG("\n"); - } - - // check the error status of this framebuffer */ - GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - - // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort - if (error != 0) { - int w, h; - GLint fmt; - glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); - glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w); - glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h); - - switch(error) - { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: - ERROR_LOG("Error! missing a required image/buffer attachment!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: - ERROR_LOG("Error! has no images/buffers attached!\n"); - break; -// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT: -// ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n"); -// break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: - ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: - ERROR_LOG("Error! colorbuffer attachments have different types!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: - ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: - ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); - break; - default: - ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT()!\n"); - break; - } - } -} - -void HandleCgError(CGcontext ctx, CGerror err, void* appdata) -{ - if( s_bOutputCgErrors ) { - ERROR_LOG("Cg error: %s\n", cgGetErrorString(err)); - const char* listing = cgGetLastListing(g_cgcontext); - if (listing != NULL) { - ERROR_LOG(" last listing: %s\n", listing); - } - // glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); - // printf("pos: %d\n", loc); - } -} +#include "Globals.h"
+#include <list>
+
+#include "GLInit.h"
+#include "Render.h"
+#include "OpcodeDecoding.h"
+#include "BPStructs.h"
+#include "TextureMngr.h"
+#include "rasterfont.h"
+#include "VertexShader.h"
+#include "PixelShader.h"
+#include "VertexLoader.h"
+
+
+#ifdef _WIN32
+#include "EmuWindow.h"
+#else
+#endif
+
+struct MESSAGE
+{
+ MESSAGE() {}
+ MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; }
+ char str[255];
+ u32 dwTimeStamp;
+};
+
+CGcontext g_cgcontext;
+CGprofile g_cgvProf, g_cgfProf;
+
+static int g_MaxTexWidth = 0, g_MaxTexHeight = 0;
+static RasterFont* s_pfont = NULL;
+static std::list<MESSAGE> s_listMsgs;
+static bool s_bFullscreen = false;
+static bool s_bOutputCgErrors = true;
+static int nZBufferRender = 0; // if > 0, then using zbuffer render
+static u32 s_uFramebuffer = 0;
+static u32 s_RenderTargets[1] = {0}, s_DepthTarget = 0, s_ZBufferTarget = 0;
+static bool s_bATIDrawBuffers = false, s_bHaveStencilBuffer = false;
+static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal;
+static int s_nCurTarget = 0;
+bool g_bBlendLogicOp = false;
+
+
+void HandleCgError(CGcontext ctx, CGerror err, void* appdata);
+
+
+bool Renderer::Create2()
+{
+ bool bSuccess = true;
+ GLenum err = GL_NO_ERROR;
+ g_cgcontext = cgCreateContext();
+ cgGetError();
+ cgSetErrorHandler(HandleCgError, NULL);
+
+ // fill the opengl extension map
+ const char* ptoken = (const char*)glGetString( GL_EXTENSIONS );
+ if (ptoken == NULL) return false;
+
+ __Log("Supported OpenGL Extensions:\n");
+ __Log(ptoken); // write to the log file
+ __Log("\n");
+
+ if( strstr(ptoken, "GL_EXT_blend_logic_op") != NULL )
+ g_bBlendLogicOp = true;
+ if( strstr(ptoken, "ATI_draw_buffers") != NULL )
+ s_bATIDrawBuffers = true;
+
+ s_bFullscreen = g_Config.bFullscreen;
+
+ if (glewInit() != GLEW_OK) {
+ ERROR_LOG("glewInit() failed!\n");
+ return false;
+ }
+
+ if (!GLEW_EXT_framebuffer_object) {
+ ERROR_LOG("*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\n");
+ bSuccess = false;
+ }
+
+ if (!GLEW_EXT_secondary_color) {
+ ERROR_LOG("*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\n");
+ bSuccess = false;
+ }
+
+ int numvertexattribs=0;
+ glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs);
+
+ if (numvertexattribs < 11) {
+ ERROR_LOG("*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\n", numvertexattribs);
+ bSuccess = false;
+ }
+
+ if (!bSuccess)
+ return false;
+
+#ifdef _WIN32
+ if (WGLEW_EXT_swap_control)
+ wglSwapIntervalEXT(0);
+ else
+ ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n");
+#else
+ if (glXSwapIntervalSGI)
+ glXSwapIntervalSGI(0);
+ else
+ ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n");
+#endif
+
+ // check the max texture width and height
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &g_MaxTexWidth);
+ g_MaxTexHeight = g_MaxTexWidth;
+
+ GL_REPORT_ERROR();
+ if (err != GL_NO_ERROR) bSuccess = false;
+
+ if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers)
+ glDrawBuffers = glDrawBuffersARB;
+
+ glGenFramebuffersEXT( 1, &s_uFramebuffer);
+ if (s_uFramebuffer == 0) {
+ ERROR_LOG("failed to create the renderbuffer\n");
+ }
+
+ _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT );
+ glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer );
+
+ // create the framebuffer targets
+ glGenTextures(ARRAYSIZE(s_RenderTargets), s_RenderTargets);
+ for(int i = 0; i < ARRAYSIZE(s_RenderTargets); ++i) {
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[i]);
+ // initialize to default
+ glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if( glGetError() != GL_NO_ERROR) {
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ GL_REPORT_ERROR();
+ }
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ s_nCurTarget = 0;
+
+ GL_REPORT_ERROR();
+
+ int nMaxMRT = 0;
+ glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxMRT);
+
+ if( nMaxMRT > 1 ) {
+ // create zbuffer target
+ glGenTextures(1, &s_ZBufferTarget);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget);
+ glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if( glGetError() != GL_NO_ERROR) {
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ GL_REPORT_ERROR();
+ }
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+
+ // create the depth buffer
+ glGenRenderbuffersEXT( 1, &s_DepthTarget);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_nTargetWidth, s_nTargetHeight);
+ if( glGetError() != GL_NO_ERROR ) {
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, s_nTargetWidth, s_nTargetHeight);
+ s_bHaveStencilBuffer = false;
+ }
+ else s_bHaveStencilBuffer = true;
+
+ GL_REPORT_ERROR();
+
+ // set as render targets
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget], 0 );
+ glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget );
+ GL_REPORT_ERROR();
+
+ if( s_ZBufferTarget != 0 ) {
+ // test to make sure it works
+ glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0);
+ bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT;
+ glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0);
+
+ if( bFailed ) {
+ glDeleteTextures(1, &s_ZBufferTarget);
+ s_ZBufferTarget = 0;
+ }
+ }
+
+ if( s_ZBufferTarget == 0 )
+ ERROR_LOG("disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT);
+
+ //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget );
+
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ nZBufferRender = 0;
+
+ GL_REPORT_ERROR();
+ if (err != GL_NO_ERROR) bSuccess = false;
+
+ s_pfont = new RasterFont();
+
+ SetAA(g_Config.aa);
+ GL_REPORT_ERROR();
+
+ // load the effect, find the best profiles (if any)
+ if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) {
+ ERROR_LOG("arbvp1 not supported\n");
+ return false;
+ }
+ if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) {
+ ERROR_LOG("arbfp1 not supported\n");
+ return false;
+ }
+
+ g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX);
+ g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);//CG_PROFILE_ARBFP1;
+ //cgGLSetOptimalOptions(g_cgvProf);
+ //cgGLSetOptimalOptions(g_cgfProf);
+
+ //ERROR_LOG("max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf));
+ int nenvvertparams, nenvfragparams, naddrregisters[2];
+ glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &nenvvertparams);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, &nenvfragparams);
+ glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &naddrregisters[0]);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, &naddrregisters[1]);
+ __Log("max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams);
+ __Log("max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]);
+
+ if( nenvvertparams < 238 )
+ ERROR_LOG("not enough vertex shader environment constants!!\n");
+
+#ifndef _DEBUG
+ cgGLSetDebugMode(GL_FALSE);
+#endif
+
+ if( cgGetError() != CG_NO_ERROR ) {
+ ERROR_LOG("cg error\n");
+ return false;
+ }
+
+ //glEnable(GL_POLYGON_OFFSET_FILL);
+ //glEnable(GL_POLYGON_OFFSET_LINE);
+ //glPolygonOffset(0, 1);
+
+ if (!Initialize())
+ return false;
+
+ return glGetError() == GL_NO_ERROR && bSuccess;
+}
+
+void Renderer::Shutdown(void)
+{
+ SAFE_DELETE(s_pfont);
+
+ if( g_cgcontext != 0 ) {
+ cgDestroyContext(g_cgcontext);
+ g_cgcontext = 0;
+ }
+
+ if( s_RenderTargets[0] ) {
+ glDeleteTextures(ARRAYSIZE(s_RenderTargets), s_RenderTargets);
+ memset(s_RenderTargets, 0, sizeof(s_RenderTargets));
+ }
+ if( s_DepthTarget ) {
+ glDeleteRenderbuffersEXT(1, &s_DepthTarget); s_DepthTarget = 0;
+ }
+
+ if (s_uFramebuffer != 0) {
+ glDeleteFramebuffersEXT( 1, &s_uFramebuffer);
+ s_uFramebuffer = 0;
+ }
+}
+
+
+bool Renderer::Initialize()
+{
+ glStencilFunc(GL_ALWAYS, 0, 0);
+ glBlendFunc(GL_ONE, GL_ONE);
+
+ glViewport(0,0,s_nTargetWidth,s_nTargetWidth); // Reset The Current Viewport
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glShadeModel(GL_SMOOTH);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClearDepth(1.0f);
+ glEnable(GL_DEPTH_TEST);
+ glDisable(GL_LIGHTING);
+ glDepthFunc(GL_LEQUAL);
+
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // perspective correct interpolation of colors and tex coords
+
+ // setup the default vertex declaration
+ glDisable(GL_STENCIL_TEST);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(0,0,nBackbufferWidth,nBackbufferHeight);
+ glBlendColorEXT(0, 0, 0, 0.5f);
+ glClearDepth(1.0f);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ //Renderer::SetZBufferRender();
+
+ // legacy multitexturing: select texture channel only
+ glActiveTexture(GL_TEXTURE0);
+ glClientActiveTexture(GL_TEXTURE0);
+ glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
+
+ s_RenderMode = Renderer::RM_Normal;
+
+ GLenum err = GL_NO_ERROR;
+ GL_REPORT_ERROR();
+ return err == GL_NO_ERROR;
+}
+
+void Renderer::AddMessage(const char* pstr, u32 ms)
+{
+ s_listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms));
+}
+
+void Renderer::ProcessMessages()
+{
+ if (s_listMsgs.size() > 0) {
+ int left = 25, top = 15;
+ list<MESSAGE>::iterator it = s_listMsgs.begin();
+
+ while( it != s_listMsgs.end() ) {
+ DrawText(it->str, left+1, top+1, 0xff000000);
+ DrawText(it->str, left, top, 0xffffff30);
+ top += 15;
+
+ if ((int)(it->dwTimeStamp - timeGetTime()) < 0)
+ it = s_listMsgs.erase(it);
+ else ++it;
+ }
+ }
+}
+
+void Renderer::DrawText(const char* pstr, int left, int top, u32 color)
+{
+ glColor3f(((color>>16) & 0xff)/255.0f, ((color>>8) & 0xff)/255.0f, (color & 0xff)/255.0f);
+ s_pfont->printString(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0);
+}
+
+void Renderer::SetAA(int aa)
+{
+
+}
+
+void Renderer::ReinitView(int nNewWidth, int nNewHeight)
+{
+ int oldscreen = s_bFullscreen;
+
+ OpenGL_Shutdown();
+ int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight;
+ if (!OpenGL_Create(g_VideoInitialize, nNewWidth, nNewHeight)) {//nNewWidth&~7, nNewHeight&~7) ) {
+ ERROR_LOG("Failed to recreate, reverting to old settings\n");
+ if (!OpenGL_Create(g_VideoInitialize, oldwidth, oldheight)) {
+ SysMessage("Failed to revert, exiting...\n");
+ // TODO - don't takedown the entire emu
+ exit(0);
+ }
+ }
+ OpenGL_MakeCurrent();
+
+ if (oldscreen && !g_Config.bFullscreen) { // if transitioning from full screen
+#ifdef _WIN32
+ RECT rc;
+ rc.left = 0; rc.top = 0;
+ rc.right = nNewWidth; rc.bottom = nNewHeight;
+ AdjustWindowRect(&rc, EmuWindow::g_winstyle, FALSE);
+
+ RECT rcdesktop;
+ GetWindowRect(GetDesktopWindow(), &rcdesktop);
+
+ SetWindowLong( EmuWindow::GetWnd(), GWL_STYLE, EmuWindow::g_winstyle );
+ SetWindowPos(EmuWindow::GetWnd(), HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2,
+ ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2,
+ rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW);
+ UpdateWindow(EmuWindow::GetWnd());
+#else // linux
+#endif
+ }
+
+ nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16;
+ nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16;
+}
+
+int Renderer::GetTargetWidth()
+{
+ return s_nTargetWidth;
+}
+
+bool Renderer::CanBlendLogicOp()
+{
+ return g_bBlendLogicOp;
+}
+
+int Renderer::GetTargetHeight()
+{
+ return s_nTargetHeight;
+}
+
+void Renderer::SetRenderTarget(u32 targ)
+{
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, targ!=0?targ:s_RenderTargets[s_nCurTarget], 0 );
+}
+
+void Renderer::SetDepthTarget(u32 targ)
+{
+ glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targ != 0 ? targ : s_DepthTarget );
+}
+
+void Renderer::SetFramebuffer(u32 fb)
+{
+ glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb != 0 ? fb : s_uFramebuffer );
+}
+
+u32 Renderer::GetRenderTarget()
+{
+ return s_RenderTargets[s_nCurTarget];
+}
+
+void Renderer::ResetGLState()
+{
+ glDisable(GL_SCISSOR_TEST);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glDisable(GL_BLEND);
+ glDepthMask(GL_FALSE);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glDisable( GL_VERTEX_PROGRAM_ARB );
+ glDisable( GL_FRAGMENT_PROGRAM_ARB );
+}
+
+void Renderer::RestoreGLState()
+{
+ glEnable(GL_SCISSOR_TEST);
+
+ if (bpmem.genMode.cullmode>0) glEnable(GL_CULL_FACE);
+ if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST);
+ if (bpmem.blendmode.blendenable) glEnable(GL_BLEND);
+ if(bpmem.zmode.updateenable) glDepthMask(GL_TRUE);
+
+ glEnable( GL_VERTEX_PROGRAM_ARB );
+ glEnable( GL_FRAGMENT_PROGRAM_ARB );
+ SetColorMask();
+}
+
+bool Renderer::IsUsingATIDrawBuffers()
+{
+ return s_bATIDrawBuffers;
+}
+
+bool Renderer::HaveStencilBuffer()
+{
+ return s_bHaveStencilBuffer;
+}
+
+void Renderer::SetZBufferRender()
+{
+ nZBufferRender = 10; // give it 10 frames
+ GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
+ glDrawBuffers(2, s_drawbuffers);
+ glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0);
+ _assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT);
+}
+
+void Renderer::FlushZBufferAlphaToTarget()
+{
+ ResetGLState();
+
+ SetRenderTarget(0);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+
+ glViewport(0, 0, GetTargetWidth()<<g_AAx, GetTargetHeight()<<g_AAy);
+
+ // texture map s_RenderTargets[s_curtarget] onto the main buffer
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget);
+ TextureMngr::EnableTexRECT(0);
+ // disable all other stages
+ for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i);
+ GL_REPORT_ERRORD();
+
+ // setup the stencil to only accept pixels that have been written
+ glStencilFunc(GL_EQUAL, 1, 0xff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(-1,-1);
+ glTexCoord2f(0, (float)(GetTargetHeight()<<g_AAy)); glVertex2f(-1,1);
+ glTexCoord2f((float)(GetTargetWidth()<<g_AAx), (float)(GetTargetWidth()<<g_AAy)); glVertex2f(1,1);
+ glTexCoord2f((float)(GetTargetWidth()<<g_AAx), 0); glVertex2f(1,-1);
+ glEnd();
+
+ GL_REPORT_ERRORD();
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
+ RestoreGLState();
+}
+
+void Renderer::SetRenderMode(RenderMode mode)
+{
+ if( !s_bHaveStencilBuffer && mode == RM_ZBufferAlpha )
+ mode = RM_ZBufferOnly;
+
+ if( s_RenderMode == mode )
+ return;
+
+ if( mode == RM_Normal ) {
+ // flush buffers
+ if( s_RenderMode == RM_ZBufferAlpha ) {
+ FlushZBufferAlphaToTarget();
+ glDisable(GL_STENCIL_TEST);
+ }
+ SetColorMask();
+ SetRenderTarget(0);
+ SetZBufferRender();
+ GL_REPORT_ERRORD();
+ }
+ else if( s_RenderMode == RM_Normal ) {
+ // setup buffers
+ _assert_(GetZBufferTarget() && bpmem.zmode.updateenable);
+
+ if( mode == RM_ZBufferAlpha ) {
+ glEnable(GL_STENCIL_TEST);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glStencilFunc(GL_ALWAYS, 1, 0xff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
+
+ glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ GL_REPORT_ERRORD();
+ }
+ else {
+ _assert_(GetZBufferTarget());
+ _assert_(s_bHaveStencilBuffer);
+
+ if( mode == RM_ZBufferOnly ) {
+ // flush and remove stencil
+ _assert_(s_RenderMode==RM_ZBufferAlpha);
+ FlushZBufferAlphaToTarget();
+ glDisable(GL_STENCIL_TEST);
+
+ SetRenderTarget(s_ZBufferTarget);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ GL_REPORT_ERRORD();
+ }
+ else {
+ _assert_(mode == RM_ZBufferAlpha&&s_RenderMode==RM_ZBufferOnly);
+
+ // setup stencil
+ glEnable(GL_STENCIL_TEST);
+ glClearStencil(0);
+ glClear(GL_STENCIL_BUFFER_BIT);
+ glStencilFunc(GL_ALWAYS, 1, 0xff);
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ }
+ }
+
+ s_RenderMode = mode;
+}
+
+Renderer::RenderMode Renderer::GetRenderMode()
+{
+ return s_RenderMode;
+}
+
+u32 Renderer::GetZBufferTarget()
+{
+ return nZBufferRender > 0 ? s_ZBufferTarget : 0;
+}
+
+void Renderer::Swap(const TRectangle& rc)
+{
+ OpenGL_Update(); // just updates the render window position and the backbuffer size
+
+ DVProfileFunc _pf("Renderer::Swap");
+
+ Renderer::SetRenderMode(Renderer::RM_Normal);
+
+ // render to the real buffer now
+ glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
+ glViewport(0, 0, nBackbufferWidth, nBackbufferHeight);
+
+ ResetGLState();
+
+ // texture map s_RenderTargets[s_curtarget] onto the main buffer
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget]);
+ TextureMngr::EnableTexRECT(0);
+ // disable all other stages
+ for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i);
+ GL_REPORT_ERRORD();
+
+
+ float FactorW = (float)s_nTargetWidth / (float)nBackbufferWidth;
+ float FactorH = (float)s_nTargetHeight / (float)nBackbufferHeight;
+
+ float Max = (FactorW < FactorH) ? FactorH : FactorW;
+ float Temp = 1 / Max;
+ FactorW *= Temp;
+ FactorH *= Temp;
+
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(0, 0); glVertex2f(-FactorW,-FactorH);
+ glTexCoord2f(0, (float)s_nTargetHeight); glVertex2f(-FactorW,FactorH);
+ glTexCoord2f((float)s_nTargetWidth, (float)s_nTargetHeight); glVertex2f(FactorW,FactorH);
+ glTexCoord2f((float)s_nTargetWidth, 0); glVertex2f(FactorW,-FactorH);
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0);
+ TextureMngr::DisableStage(0);
+
+// static int fpscount = 0;
+// static float s_fps = 0;
+// static u32 lasttime = timeGetTime();
+//
+// if( ++fpscount >= 16 ) {
+// s_fps = 16*1000.0f/(float)(timeGetTime() - lasttime);
+// lasttime = timeGetTime();
+// fpscount = 0;
+// }
+//
+// char strfps[25];
+// sprintf(strfps, "fps: %2.1f\n", s_fps);
+// Renderer::DrawText(strfps, 20, 20, 0xFF00FFFF);
+
+ if (g_Config.bOverlayStats) {
+ char st[2048];
+ char *p = st;
+ p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
+ p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
+ p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
+ p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
+ p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
+ p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
+ p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
+ p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
+ p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
+ p+=sprintf(p,"Num strip joins: %i\n",stats.numJoins);
+ p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
+ p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
+ p+=sprintf(p,"Num bad commands: %i%s\n",stats.thisFrame.numBadCommands,stats.thisFrame.numBadCommands?"!!!":"");
+ p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
+ p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
+ p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
+ p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
+ p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
+ p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
+
+ Renderer::DrawText(st, 20, 20, 0xFF00FFFF);
+ }
+
+#if defined(DVPROFILE)
+ if (g_bWriteProfile) {
+ //g_bWriteProfile = 0;
+ static int framenum = 0;
+ const int UPDATE_FRAMES = 8;
+ if (++framenum >= UPDATE_FRAMES) {
+ DVProfWrite("prof.txt", UPDATE_FRAMES);
+ DVProfClear();
+ framenum = 0;
+ }
+ }
+#endif
+
+ // copy the rendered from to the real window
+ OpenGL_SwapBuffers();
+
+ GL_REPORT_ERRORD();
+
+ //clean out old stuff from caches
+ frameCount++;
+ PixelShaderMngr::Cleanup();
+ TextureMngr::Cleanup();
+
+ // New frame
+ stats.ResetFrame();
+
+ glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer );
+
+// s_nCurTarget = !s_nCurTarget;
+// SetRenderTarget(0);
+
+ if( nZBufferRender > 0 ) {
+ if( --nZBufferRender == 0 ) {
+ // turn off
+ nZBufferRender = 0;
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0);
+ Renderer::SetRenderMode(RM_Normal); // turn off any zwrites
+ }
+ }
+
+ RestoreGLState();
+ GL_REPORT_ERRORD();
+
+ g_Config.iSaveTargetId = 0;
+
+ // for testing zbuffer targets
+ //Renderer::SetZBufferRender();
+ //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight());
+}
+
+bool Renderer::SaveRenderTarget(const char* filename, int jpeg)
+{
+ bool bflip = true;
+ vector<u32> data(s_nTargetWidth*s_nTargetHeight);
+ glReadPixels(0, 0, s_nTargetWidth, s_nTargetHeight, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]);
+ if (glGetError() != GL_NO_ERROR)
+ return false;
+
+ if (bflip) {
+ // swap scanlines
+ vector<u32> scanline(s_nTargetWidth);
+ for(u32 i = 0; i < s_nTargetHeight/2; ++i) {
+ memcpy(&scanline[0], &data[i*s_nTargetWidth], s_nTargetWidth*4);
+ memcpy(&data[i*s_nTargetWidth], &data[(s_nTargetHeight-i-1)*s_nTargetWidth], s_nTargetWidth*4);
+ memcpy(&data[(s_nTargetHeight-i-1)*s_nTargetWidth], &scanline[0], s_nTargetWidth*4);
+ }
+ }
+
+ if (jpeg) return SaveJPEG(filename, s_nTargetWidth, s_nTargetHeight, &data[0], 70);
+
+ return SaveTGA(filename, s_nTargetWidth, s_nTargetHeight, &data[0]);
+}
+
+void Renderer::SetCgErrorOutput(bool bOutput)
+{
+ s_bOutputCgErrors = bOutput;
+}
+
+void HandleGLError()
+{
+ const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
+ if (pstr != NULL && pstr[0] != 0 ) {
+ GLint loc=0;
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc);
+ ERROR_LOG("program error at %d: ", loc);
+ ERROR_LOG((char*)pstr);
+ ERROR_LOG("\n");
+ }
+
+ // check the error status of this framebuffer */
+ GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort
+ if (error != 0) {
+ int w, h;
+ GLint fmt;
+ glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt);
+ glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, &w);
+ glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, &h);
+
+ switch(error)
+ {
+ case GL_FRAMEBUFFER_COMPLETE_EXT:
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
+ ERROR_LOG("Error! missing a required image/buffer attachment!\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ ERROR_LOG("Error! has no images/buffers attached!\n");
+ break;
+// case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
+// ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n");
+// break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ ERROR_LOG("Error! has mismatched image/buffer dimensions!\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ ERROR_LOG("Error! colorbuffer attachments have different types!\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ ERROR_LOG("Error! trying to draw to non-attached color buffer!\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ ERROR_LOG("Error! trying to read from a non-attached color buffer!\n");
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ ERROR_LOG("Error! format is not supported by current graphics card/driver!\n");
+ break;
+ default:
+ ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT()!\n");
+ break;
+ }
+ }
+}
+
+void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
+{
+ if( s_bOutputCgErrors ) {
+ ERROR_LOG("Cg error: %s\n", cgGetErrorString(err));
+ const char* listing = cgGetLastListing(g_cgcontext);
+ if (listing != NULL) {
+ ERROR_LOG(" last listing: %s\n", listing);
+ }
+ // glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc);
+ // printf("pos: %d\n", loc);
+ }
+}
diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp index 12e97003b3..0a7015557f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp @@ -23,9 +23,9 @@ namespace EmuWindow
{
- HWND m_hWnd;
+ HWND m_hWnd = NULL;
HWND m_hParent = NULL;
- HINSTANCE m_hInstance;
+ HINSTANCE m_hInstance = NULL;
WNDCLASSEX wndClass;
const TCHAR m_szClassName[] = "DolphinEmuWnd";
int g_winstyle;
|
