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); - m_hWnd = CreateWindow(m_szClassName, title, - style, - rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, - parent, NULL, hInstance, NULL ); + int w = rc.right - rc.left; + int h = rc.bottom - rc.top; + + 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 - -#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 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::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()< 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 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 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 + +#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 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::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()< 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 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 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;