summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp3
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.cpp57
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/EmuWindow.h1
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Globals.cpp2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Globals.h1
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/Render.cpp14
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/main.cpp28
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/resource.h2
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/resource.rc15
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Render.cpp1642
-rw-r--r--Source/Plugins/Plugin_VideoOGL/Src/Windows/EmuWindow.cpp4
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;