OGL plugin: +Autoscale option (attempts to remove borders, even without XFB). Lots of cleanup, especially around aspect ratio and similar stuff. MP2 scanner still broken, wonder when that happened?

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2470 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-02-28 16:33:59 +00:00
parent 11fd8062ad
commit 6dc4194767
22 changed files with 460 additions and 729 deletions

View File

@ -118,4 +118,10 @@ namespace
#define GC_ALIGNED64_DECL(x) __attribute((aligned(64))) x #define GC_ALIGNED64_DECL(x) __attribute((aligned(64))) x
#endif // WIN32 #endif // WIN32
// A macro to disallow the copy constructor and operator= functions
// This should be used in the private: declarations for a class
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
void operator=(const TypeName&)
#endif // COMMON_H #endif // COMMON_H

View File

@ -89,9 +89,6 @@ struct PortableVertexDeclaration
// all the data loading code must always be made compatible. // all the data loading code must always be made compatible.
class NativeVertexFormat class NativeVertexFormat
{ {
protected:
NativeVertexFormat() {}
public: public:
virtual ~NativeVertexFormat() {} virtual ~NativeVertexFormat() {}
@ -103,6 +100,13 @@ public:
// TODO: move these in under private: // TODO: move these in under private:
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present. u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
protected:
// Let subclasses construct.
NativeVertexFormat() {}
private:
DISALLOW_COPY_AND_ASSIGN(NativeVertexFormat);
}; };
#endif // _NATIVEVERTEXFORMAT_H #endif // _NATIVEVERTEXFORMAT_H

View File

@ -23,6 +23,8 @@
#include <string> #include <string>
#include "Common.h"
#include "CPMemory.h" #include "CPMemory.h"
#include "DataReader.h" #include "DataReader.h"
#include "NativeVertexFormat.h" #include "NativeVertexFormat.h"
@ -103,6 +105,8 @@ private:
void WriteGetVariable(int bits, Gen::OpArg dest, void *address); void WriteGetVariable(int bits, Gen::OpArg dest, void *address);
void WriteSetVariable(int bits, void *address, Gen::OpArg dest); void WriteSetVariable(int bits, void *address, Gen::OpArg dest);
DISALLOW_COPY_AND_ASSIGN(VertexLoader);
}; };
#endif #endif

View File

@ -37,7 +37,6 @@
#include "XFB.h" #include "XFB.h"
#include "main.h" #include "main.h"
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// State translation lookup tables // State translation lookup tables
// ------------- // -------------
@ -383,8 +382,8 @@ void BPWritten(int addr, int changes, int newval)
(int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x + 1)), (int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x + 1)),
(int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y + 1)) (int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y + 1))
}; };
float MValueX = OpenGL_GetXmax(); float MValueX = Renderer::GetTargetScaleX();
float MValueY = OpenGL_GetYmax(); float MValueY = Renderer::GetTargetScaleY();
// Need another rc here to get it to scale. // Need another rc here to get it to scale.
// Here the bottom right is the out of the rectangle. // Here the bottom right is the out of the rectangle.
TRectangle multirc = { TRectangle multirc = {
@ -407,9 +406,9 @@ void BPWritten(int addr, int changes, int newval)
if (g_Config.bEFBCopyDisable) if (g_Config.bEFBCopyDisable)
{ {
/* We already have this in Render.cpp that we call when (PE_copy.clear) is true. But we need a separate one /* We already have this in Render.cpp that we call when (PE_copy.clear) is true. But we need a separate one
here because UpdateViewport() is not run when this otion is set? */ here because UpdateViewport() is not run when this option is set? */
glViewport(rc.left,rc.bottom, rc.right,rc.top); glViewport(rc.left, rc.bottom, rc.right,rc.top);
glScissor(rc.left,rc.bottom, rc.right,rc.top); glScissor(rc.left, rc.bottom, rc.right,rc.top);
// Logging // Logging
GLScissorX = rc.left; GLScissorX = rc.left;
GLScissorY = rc.bottom; GLScissorY = rc.bottom;
@ -560,7 +559,7 @@ void BPWritten(int addr, int changes, int newval)
break; break;
default: default:
switch(addr & 0xFC) //texture sampler filter switch (addr & 0xFC) //texture sampler filter
{ {
case 0x28: // tevorder 0-3 case 0x28: // tevorder 0-3
case 0x2C: // tevorder 4-7 case 0x2C: // tevorder 4-7
@ -571,7 +570,6 @@ void BPWritten(int addr, int changes, int newval)
PixelShaderManager::SetTevOrderChanged(addr - 0x28); PixelShaderManager::SetTevOrderChanged(addr - 0x28);
} }
break; break;
case 0x80: // TEX MODE 0 case 0x80: // TEX MODE 0
case 0xA0: case 0xA0:
if (changes) if (changes)

View File

@ -40,17 +40,15 @@ void Config::Load()
iniFile.Get("Hardware", "FullscreenRes", &temp, "640x480"); iniFile.Get("Hardware", "FullscreenRes", &temp, "640x480");
strncpy(iFSResolution, temp.c_str(), 16); strncpy(iFSResolution, temp.c_str(), 16);
iniFile.Get("Settings", "Backend", &temp, "");
strncpy(iBackend, temp.c_str(), 16);
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0); // Hardware
iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false); iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false);
iniFile.Get("Settings", "StretchToFit", &bStretchToFit, true); iniFile.Get("Settings", "StretchToFit", &bNativeResolution, true);
iniFile.Get("Settings", "KeepAR_4_3", &bKeepAR43, false); iniFile.Get("Settings", "KeepAR_4_3", &bKeepAR43, false);
iniFile.Get("Settings", "KeepAR_16_9", &bKeepAR169, false); iniFile.Get("Settings", "KeepAR_16_9", &bKeepAR169, false);
iniFile.Get("Settings", "Crop", &bCrop, false); iniFile.Get("Settings", "Crop", &bCrop, false);
iniFile.Get("Settings", "HideCursor", &bHideCursor, false); iniFile.Get("Settings", "HideCursor", &bHideCursor, false);
iniFile.Get("Settings", "UseXFB", &bUseXFB, 0);
iniFile.Get("Settings", "AutoScale", &bAutoScale, true);
iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings iniFile.Get("Settings", "SafeTextureCache", &bSafeTextureCache, false); // Settings
iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings iniFile.Get("Settings", "ShowFPS", &bShowFPS, false); // Settings
@ -69,12 +67,11 @@ void Config::Load()
strcpy(texDumpPath, s.c_str()); strcpy(texDumpPath, s.c_str());
else { else {
strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1); strncpy(texDumpPath, s.c_str(), sizeof(texDumpPath)-1);
texDumpPath[sizeof(texDumpPath)-1] = 0; texDumpPath[sizeof(texDumpPath) - 1] = 0;
} }
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0); iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0); iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
iniFile.Get("Settings", "UseXFB", &bUseXFB, 0);
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0); iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0); iniFile.Get("Settings", "DisableLighting", &bDisableLighting, 0);
iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0); iniFile.Get("Settings", "DisableTexturing", &bDisableTexturing, 0);
@ -97,13 +94,13 @@ void Config::Save()
iniFile.Set("Hardware", "FullscreenRes", iFSResolution); iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
iniFile.Set("Hardware", "Fullscreen", bFullscreen); iniFile.Set("Hardware", "Fullscreen", bFullscreen);
iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe);
iniFile.Set("Settings", "StretchToFit", bStretchToFit); iniFile.Set("Settings", "StretchToFit", bNativeResolution);
iniFile.Set("Settings", "KeepAR_4_3", bKeepAR43); iniFile.Set("Settings", "KeepAR_4_3", bKeepAR43);
iniFile.Set("Settings", "KeepAR_16_9", bKeepAR169); iniFile.Set("Settings", "KeepAR_16_9", bKeepAR169);
iniFile.Set("Settings", "Crop", bCrop); iniFile.Set("Settings", "Crop", bCrop);
iniFile.Set("Settings", "HideCursor", bHideCursor); iniFile.Set("Settings", "HideCursor", bHideCursor);
iniFile.Set("Settings", "Backend", iBackend); iniFile.Set("Settings", "UseXFB", bUseXFB);
iniFile.Set("Settings", "AutoScale", bAutoScale);
iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache); iniFile.Set("Settings", "SafeTextureCache", bSafeTextureCache);
iniFile.Set("Settings", "ShowFPS", bShowFPS); iniFile.Set("Settings", "ShowFPS", bShowFPS);
@ -117,7 +114,6 @@ void Config::Save()
iniFile.Set("Settings", "TexDumpPath", texDumpPath); iniFile.Set("Settings", "TexDumpPath", texDumpPath);
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable); iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter); iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
iniFile.Set("Settings", "UseXFB", bUseXFB);
iniFile.Set("Settings", "Wireframe", bWireFrame); iniFile.Set("Settings", "Wireframe", bWireFrame);
iniFile.Set("Settings", "DisableLighting", bDisableLighting); iniFile.Set("Settings", "DisableLighting", bDisableLighting);
iniFile.Set("Settings", "DisableTexturing", bDisableTexturing); iniFile.Set("Settings", "DisableTexturing", bDisableTexturing);

View File

@ -18,6 +18,8 @@
#ifndef _CONFIG_H #ifndef _CONFIG_H
#define _CONFIG_H #define _CONFIG_H
#include "Common.h"
// Log in two categories, and save three other options in the same byte // Log in two categories, and save three other options in the same byte
#define CONF_LOG 1 #define CONF_LOG 1
#define CONF_PRIMLOG 2 #define CONF_PRIMLOG 2
@ -25,6 +27,7 @@
#define CONF_SAVETARGETS 8 #define CONF_SAVETARGETS 8
#define CONF_SAVESHADERS 16 #define CONF_SAVESHADERS 16
// NEVER inherit from this class.
struct Config struct Config
{ {
Config(); Config();
@ -33,17 +36,17 @@ struct Config
// General // General
bool bFullscreen; bool bFullscreen;
bool bHideCursor;
bool renderToMainframe; bool renderToMainframe;
// Resolution control
char iFSResolution[16]; char iFSResolution[16];
char iWindowedRes[16]; char iWindowedRes[16];
char iBackend[16];
// stretch to fit should be split into two options, I think - one for low resolution backbuffer, bool bNativeResolution; // Should possibly be augmented with 2x, 4x native.
// one for ignore aspect ratio. I guess KeepAR sort of does that. Anyway, these should be rethought. bool bKeepAR43, bKeepAR169, bCrop; // Aspect ratio controls.
bool bStretchToFit; bool bUseXFB;
bool bKeepAR43, bKeepAR169, bCrop; bool bAutoScale; // Removes annoying borders without using XFB. Doesn't always work perfectly.
bool bHideCursor;
bool bSafeTextureCache;
// Enhancements // Enhancements
int iMultisampleMode; int iMultisampleMode;
@ -59,7 +62,6 @@ struct Config
bool bTexFmtOverlayCenter; bool bTexFmtOverlayCenter;
// Render // Render
bool bUseXFB;
bool bWireFrame; bool bWireFrame;
bool bDisableLighting; bool bDisableLighting;
bool bDisableTexturing; bool bDisableTexturing;
@ -74,6 +76,7 @@ struct Config
bool bProjectionHax1; bool bProjectionHax1;
bool bProjectionHax2; bool bProjectionHax2;
bool bCopyEFBToRAM; bool bCopyEFBToRAM;
bool bSafeTextureCache;
int iLog; // CONF_ bits int iLog; // CONF_ bits
int iSaveTargetId; int iSaveTargetId;
@ -81,6 +84,9 @@ struct Config
//currently unused: //currently unused:
int iCompileDLsLevel; int iCompileDLsLevel;
bool bShowShaderErrors; bool bShowShaderErrors;
private:
DISALLOW_COPY_AND_ASSIGN(Config);
}; };
extern Config g_Config; extern Config g_Config;

View File

@ -37,10 +37,9 @@ struct RECT
// Handles OpenGL and the window // Handles OpenGL and the window
// externals // Window dimensions.
int nBackbufferWidth, nBackbufferHeight; // screen width static int s_backbuffer_width;
int nXoff, nYoff; // screen offset static int s_backbuffer_height;
float MValueX, MValueY;
#ifndef _WIN32 #ifndef _WIN32
GLWindow GLWin; GLWindow GLWin;
@ -67,36 +66,14 @@ void OpenGL_SwapBuffers()
#endif #endif
} }
float OpenGL_GetXmax() { u32 OpenGL_GetBackbufferWidth() {
return MValueX; return s_backbuffer_width;
} }
float OpenGL_GetYmax() { u32 OpenGL_GetBackbufferHeight() {
return MValueY; return s_backbuffer_height;
} }
int OpenGL_GetXoff() {
return nXoff;
}
int OpenGL_GetYoff() {
return nYoff;
}
u32 OpenGL_GetWidth() {
return nBackbufferWidth;
}
u32 OpenGL_GetHeight() {
return nBackbufferHeight;
}
void OpenGL_SetSize(u32 width, u32 height) {
nBackbufferWidth = width;
nBackbufferHeight = height;
}
void OpenGL_SetWindowText(const char *text) void OpenGL_SetWindowText(const char *text)
{ {
#if USE_SDL #if USE_SDL
@ -123,7 +100,7 @@ void OpenGL_SetWindowText(const char *text)
unsigned int Callback_PeekMessages() unsigned int Callback_PeekMessages()
{ {
#ifdef _WIN32 #ifdef _WIN32
//TODO: peekmessage // TODO: peekmessage
MSG msg; MSG msg;
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{ {
@ -137,6 +114,7 @@ unsigned int Callback_PeekMessages()
return FALSE; return FALSE;
#endif #endif
} }
// Show the current FPS // Show the current FPS
void UpdateFPSDisplay(const char *text) void UpdateFPSDisplay(const char *text)
{ {
@ -187,40 +165,17 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
#endif #endif
// ---------------------------- // ----------------------------
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// Control window size and picture scaling // Control window size and picture scaling
// ------------------ // ------------------
// nBackbufferWidth and nBackbufferHeight = Screen resolution from ini, or 640x480 s_backbuffer_width = _twidth;
// See OpenGL_Update() for documentation of the other variables s_backbuffer_height = _theight;
// ------------------
nBackbufferWidth = _twidth;
nBackbufferHeight = _theight;
float FactorW = 640.0f / (float)nBackbufferWidth;
float FactorH = 480.0f / (float)nBackbufferHeight;
float Max = (FactorW < FactorH) ? FactorH : FactorW;
if (g_Config.bStretchToFit)
{
MValueX = 1.0f / FactorW;
MValueY = 1.0f / FactorH;
nXoff = 0;
nYoff = 0;
}
else
{
MValueX = 1.0f / Max;
MValueY = 1.0f / Max;
nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2);
nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2);
}
g_VideoInitialize.pPeekMessages = &Callback_PeekMessages; g_VideoInitialize.pPeekMessages = &Callback_PeekMessages;
g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay; g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay;
//char buff[100]; //char buff[100];
//sprintf(buff, "%i %i %d %d %d", nBackbufferWidth, nBackbufferHeight, Max, MValueX, MValueY); //sprintf(buff, "%i %i %d %d %d", s_backbuffer_width, s_backbuffer_height, Max, MValueX, MValueY);
//MessageBox(0, buff, "", 0); //MessageBox(0, buff, "", 0);
#if USE_SDL #if USE_SDL
@ -234,8 +189,8 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
//setup ogl to use double buffering //setup ogl to use double buffering
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#elif defined(HAVE_COCOA) && HAVE_COCOA #elif defined(HAVE_COCOA) && HAVE_COCOA
GLWin.width = nBackbufferWidth; GLWin.width = s_backbuffer_width;
GLWin.height = nBackbufferHeight; GLWin.height = s_backbuffer_height;
GLWin.cocoaWin = cocoaGLCreateWindow(GLWin.width, GLWin.height); GLWin.cocoaWin = cocoaGLCreateWindow(GLWin.width, GLWin.height);
GLWin.cocoaCtx = cocoaGLInit(g_Config.iMultisampleMode); GLWin.cocoaCtx = cocoaGLInit(g_Config.iMultisampleMode);
#elif defined(USE_WX) && USE_WX #elif defined(USE_WX) && USE_WX
@ -290,14 +245,14 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
GetWindowRect(GetDesktopWindow(), &rcdesktop); GetWindowRect(GetDesktopWindow(), &rcdesktop);
if (g_Config.bFullscreen) { if (g_Config.bFullscreen) {
//nBackbufferWidth = rcdesktop.right - rcdesktop.left; //s_backbuffer_width = rcdesktop.right - rcdesktop.left;
//nBackbufferHeight = rcdesktop.bottom - rcdesktop.top; //s_backbuffer_height = rcdesktop.bottom - rcdesktop.top;
DEVMODE dmScreenSettings; DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings); dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = nBackbufferWidth; dmScreenSettings.dmPelsWidth = s_backbuffer_width;
dmScreenSettings.dmPelsHeight = nBackbufferHeight; dmScreenSettings.dmPelsHeight = s_backbuffer_height;
dmScreenSettings.dmBitsPerPel = 32; dmScreenSettings.dmBitsPerPel = 32;
dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
@ -329,7 +284,7 @@ bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight
RECT rc; RECT rc;
rc.left = 0; rc.top = 0; rc.left = 0; rc.top = 0;
rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight; rc.right = s_backbuffer_width; rc.bottom = s_backbuffer_height;
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle); AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
@ -540,8 +495,8 @@ bool OpenGL_MakeCurrent()
| ( g_Config.bFullscreen ? SDL_FULLSCREEN : 0); | ( g_Config.bFullscreen ? SDL_FULLSCREEN : 0);
// Set vide mode. // Set vide mode.
// TODO: Can we use this field or is a separate field needed? // TODO: Can we use this field or is a separate field needed?
int _twidth = nBackbufferWidth; int _twidth = s_backbuffer_width;
int _theight = nBackbufferHeight; int _theight = s_backbuffer_height;
SDL_Surface *screen = SDL_SetVideoMode(_twidth, _theight, 0, videoFlags); SDL_Surface *screen = SDL_SetVideoMode(_twidth, _theight, 0, videoFlags);
if (!screen) { if (!screen) {
//TODO : Display an error message //TODO : Display an error message
@ -587,37 +542,36 @@ void OpenGL_Update()
{ {
#if USE_SDL #if USE_SDL
SDL_Surface *surface = SDL_GetVideoSurface(); SDL_Surface *surface = SDL_GetVideoSurface();
RECT rcWindow; RECT rcWindow = {0};
if (!surface) return; if (!surface)
nBackbufferWidth = surface->w; return;
nBackbufferHeight = surface->h; s_backbuffer_width = surface->w;
s_backbuffer_height = surface->h;
rcWindow.right = surface->w; rcWindow.right = surface->w;
rcWindow.bottom = surface->h; rcWindow.bottom = surface->h;
#elif defined(HAVE_COCOA) && HAVE_COCOA #elif defined(HAVE_COCOA) && HAVE_COCOA
RECT rcWindow; RECT rcWindow = {0};
rcWindow.right = GLWin.width; rcWindow.right = GLWin.width;
rcWindow.bottom = GLWin.height; rcWindow.bottom = GLWin.height;
#elif defined(USE_WX) && USE_WX #elif defined(USE_WX) && USE_WX
RECT rcWindow; RECT rcWindow = {0};
rcWindow.right = GLWin.width; rcWindow.right = GLWin.width;
rcWindow.bottom = GLWin.height; rcWindow.bottom = GLWin.height;
// TODO fill in // TODO fill in
#elif defined(_WIN32) #elif defined(_WIN32)
RECT rcWindow; RECT rcWindow;
// If we are not rendering to a child window
if (!EmuWindow::GetParentWnd()) if (!EmuWindow::GetParentWnd())
{ {
// return if we don't stretch the picture // We are not rendering to a child window - use client size.
if (!g_Config.bStretchToFit) return; GetClientRect(EmuWindow::GetWnd(), &rcWindow);
GetWindowRect(EmuWindow::GetWnd(), &rcWindow);
rcWindow.top += 25;
} }
else else
{ {
// We are rendering to a child window - use parent size.
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
} }
@ -633,8 +587,8 @@ void OpenGL_Update()
if (EmuWindow::GetParentWnd() != 0) if (EmuWindow::GetParentWnd() != 0)
::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE); ::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE);
nBackbufferWidth = width; s_backbuffer_width = width;
nBackbufferHeight = height; s_backbuffer_height = height;
#elif defined(HAVE_X11) && HAVE_X11 #elif defined(HAVE_X11) && HAVE_X11
// We just check all of our events here // We just check all of our events here
@ -684,8 +638,8 @@ void OpenGL_Update()
unsigned int borderDummy; unsigned int borderDummy;
XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
&GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth);
nBackbufferWidth = GLWin.width; s_backbuffer_width = GLWin.width;
nBackbufferHeight = GLWin.height; s_backbuffer_height = GLWin.height;
rcWindow.left = 0; rcWindow.left = 0;
rcWindow.top = 0; rcWindow.top = 0;
rcWindow.right = GLWin.width; rcWindow.right = GLWin.width;
@ -705,37 +659,6 @@ void OpenGL_Update()
} }
return; return;
#endif #endif
// ---------------------------------------------------------------------------------------
// Get the new window width and height
/* ------------------
nBackbufferWidth and nBackbufferHeight: Now the actual rendering window size
Max: The highest of w and h
nXoff and nYoff: Controls the picture's position inside the rendering window
MValueX and MValueY: Used for the picture resolution-change rescaling
// ------------------
MValueX and MValueY: Used for the picture resolution-change rescaling. It will be used in
TextureMngr and VertexShaderManager: Rescale textures on resolution changes
BPStructs.cpp: Control glScissor()
// ------------------ */
float FactorW = 640.0f / (float)nBackbufferWidth;
float FactorH = 480.0f / (float)nBackbufferHeight;
float Max = (FactorW < FactorH) ? FactorH : FactorW;
if (g_Config.bStretchToFit)
{
MValueX = 1;
MValueY = 1;
nXoff = 0;
nYoff = 0;
}
else
{
MValueX = 1.0f / Max;
MValueY = 1.0f / Max;
nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2);
nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2);
}
} }

View File

@ -119,16 +119,8 @@ extern GLWindow GLWin;
#endif #endif
float OpenGL_GetXmax(); u32 OpenGL_GetBackbufferWidth();
float OpenGL_GetYmax(); u32 OpenGL_GetBackbufferHeight();
int OpenGL_GetXoff();
int OpenGL_GetYoff();
u32 OpenGL_GetWidth();
u32 OpenGL_GetHeight();
void OpenGL_SetSize(u32 width, u32 height);
// yeah yeah, these should be hidden
//extern int nBackbufferWidth, nBackbufferHeight;
//extern int nXoff, nYoff;
bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height); bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height);
bool OpenGL_MakeCurrent(); bool OpenGL_MakeCurrent();

View File

@ -30,11 +30,12 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CHECKBOX(ID_RENDERTOMAINWINDOW, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_RENDERTOMAINWINDOW, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_FULLSCREENCB, ConfigDialog::GeneralSettingsChanged) EVT_COMBOBOX(ID_FULLSCREENCB, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_WINDOWRESOLUTIONCB, ConfigDialog::GeneralSettingsChanged) EVT_COMBOBOX(ID_WINDOWRESOLUTIONCB, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_RENDERBACKEND, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_ALIASMODECB, ConfigDialog::GeneralSettingsChanged) EVT_COMBOBOX(ID_ALIASMODECB, ConfigDialog::GeneralSettingsChanged)
EVT_CHOICE(ID_MAXANISOTROPY, ConfigDialog::GeneralSettingsChanged) EVT_CHOICE(ID_MAXANISOTROPY, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_FORCEFILTERING, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_FORCEFILTERING, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_STRETCHTOFIT, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_NATIVERESOLUTION, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_USEXFB, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_AUTOSCALE, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_KEEPAR_4_3, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_KEEPAR_4_3, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_KEEPAR_16_9, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_KEEPAR_16_9, ConfigDialog::GeneralSettingsChanged)
EVT_CHECKBOX(ID_CROP, ConfigDialog::GeneralSettingsChanged) EVT_CHECKBOX(ID_CROP, ConfigDialog::GeneralSettingsChanged)
@ -49,7 +50,6 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
EVT_CHECKBOX(ID_SHADERERRORS, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_SHADERERRORS, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_TEXFMTOVERLAY, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_TEXFMTOVERLAY, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_TEXFMTCENTER, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_USEXFB, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DUMPTEXTURES, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DISABLELIGHTING, ConfigDialog::AdvancedSettingsChanged)
EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged) EVT_CHECKBOX(ID_DISABLETEXTURING, ConfigDialog::AdvancedSettingsChanged)
@ -120,11 +120,6 @@ void ConfigDialog::AddWindowReso(char *reso)
arrayStringFor_WindowResolutionCB.Add(wxString::FromAscii(reso)); arrayStringFor_WindowResolutionCB.Add(wxString::FromAscii(reso));
} }
void ConfigDialog::AddRenderBackend(const char *backend)
{
m_RenderBackend->Append(wxString::FromAscii(backend));
}
void ConfigDialog::AddAAMode(int mode) void ConfigDialog::AddAAMode(int mode)
{ {
wxString tmp; wxString tmp;
@ -168,16 +163,21 @@ void ConfigDialog::CreateGUIControls()
m_Fullscreen->SetValue(g_Config.bFullscreen); m_Fullscreen->SetValue(g_Config.bFullscreen);
m_RenderToMainWindow = new wxCheckBox(m_PageGeneral, ID_RENDERTOMAINWINDOW, wxT("Render to main window"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_RenderToMainWindow = new wxCheckBox(m_PageGeneral, ID_RENDERTOMAINWINDOW, wxT("Render to main window"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_RenderToMainWindow->SetValue(g_Config.renderToMainframe); m_RenderToMainWindow->SetValue(g_Config.renderToMainframe);
m_StretchToFit = new wxCheckBox(m_PageGeneral, ID_STRETCHTOFIT, wxT("Stretch to fit"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_NativeResolution = new wxCheckBox(m_PageGeneral, ID_NATIVERESOLUTION, wxT("Native resolution"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Aspect ratio / positioning controls
m_KeepAR43 = new wxCheckBox(m_PageGeneral, ID_KEEPAR_4_3, wxT("Keep 4:3 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_KeepAR43 = new wxCheckBox(m_PageGeneral, ID_KEEPAR_4_3, wxT("Keep 4:3 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_KeepAR169 = new wxCheckBox(m_PageGeneral, ID_KEEPAR_16_9, wxT("Keep 16:9 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_KeepAR169 = new wxCheckBox(m_PageGeneral, ID_KEEPAR_16_9, wxT("Keep 16:9 aspect ratio"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Crop = new wxCheckBox(m_PageGeneral, ID_CROP, wxT("Crop"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_Crop = new wxCheckBox(m_PageGeneral, ID_CROP, wxT("Crop"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_UseXFB = new wxCheckBox(m_PageGeneral, ID_USEXFB, wxT("Use Real XFB"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_AutoScale = new wxCheckBox(m_PageGeneral, ID_AUTOSCALE, wxT("Auto scale (try to remove borders)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
// Default values m_NativeResolution->SetValue(g_Config.bNativeResolution);
m_StretchToFit->SetValue(g_Config.bStretchToFit);
m_KeepAR43->SetValue(g_Config.bKeepAR43); m_KeepAR43->SetValue(g_Config.bKeepAR43);
m_KeepAR169->SetValue(g_Config.bKeepAR169); m_KeepAR169->SetValue(g_Config.bKeepAR169);
m_Crop->SetValue(g_Config.bCrop); m_Crop->SetValue(g_Config.bCrop);
m_UseXFB->SetValue(g_Config.bUseXFB);
m_AutoScale->SetValue(g_Config.bAutoScale);
#ifndef _WIN32 #ifndef _WIN32
m_HideCursor = new wxCheckBox(m_PageGeneral, ID_HIDECURSOR, wxT("Hide mouse cursor"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_HideCursor = new wxCheckBox(m_PageGeneral, ID_HIDECURSOR, wxT("Hide mouse cursor"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
@ -192,17 +192,13 @@ void ConfigDialog::CreateGUIControls()
m_WindowResolutionCB = new wxComboBox(m_PageGeneral, ID_WINDOWRESOLUTIONCB, arrayStringFor_WindowResolutionCB[0], wxDefaultPosition, wxDefaultSize, arrayStringFor_WindowResolutionCB, wxCB_READONLY, wxDefaultValidator); m_WindowResolutionCB = new wxComboBox(m_PageGeneral, ID_WINDOWRESOLUTIONCB, arrayStringFor_WindowResolutionCB[0], wxDefaultPosition, wxDefaultSize, arrayStringFor_WindowResolutionCB, wxCB_READONLY, wxDefaultValidator);
m_WindowResolutionCB->SetValue(wxString::FromAscii(g_Config.iWindowedRes)); m_WindowResolutionCB->SetValue(wxString::FromAscii(g_Config.iWindowedRes));
wxStaticText *BEText = new wxStaticText(m_PageGeneral, ID_BETEXT, wxT("Rendering backend:"), wxDefaultPosition, wxDefaultSize, 0);
m_RenderBackend = new wxComboBox(m_PageGeneral, ID_RENDERBACKEND, wxEmptyString, wxDefaultPosition, wxDefaultSize, arrayStringFor_RenderBackend, 0, wxDefaultValidator);
m_RenderBackend->SetValue(wxString::FromAscii(g_Config.iBackend));
// Tool tips // Tool tips
m_Fullscreen->SetToolTip(wxT( m_Fullscreen->SetToolTip(wxT(
"This option use a separate rendering window and can only be used when" "This option use a separate rendering window and can only be used when"
" 'Render to main window' is unchecked. The only way to exit this mode\n" " 'Render to main window' is unchecked. The only way to exit this mode\n"
" is with Alt + F4 (that also close Dolphin)." " is with Alt + F4 (that also close Dolphin)."
)); ));
m_StretchToFit->SetToolTip(wxT( m_NativeResolution->SetToolTip(wxT(
"This will use the game's native resolution and stretch it to fill the" "This will use the game's native resolution and stretch it to fill the"
"\nwindow instead of changing the internal display resolution. It" "\nwindow instead of changing the internal display resolution. It"
"\nmay result in a slightly blurrier image, but it may also give a higher" "\nmay result in a slightly blurrier image, but it may also give a higher"
@ -242,12 +238,15 @@ void ConfigDialog::CreateGUIControls()
sBasic = new wxGridBagSizer(0, 0); sBasic = new wxGridBagSizer(0, 0);
sBasic->Add(m_Fullscreen, wxGBPosition(0, 0), wxGBSpan(1, 3), wxALL, 5); sBasic->Add(m_Fullscreen, wxGBPosition(0, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_RenderToMainWindow, wxGBPosition(1, 0), wxGBSpan(1, 3), wxALL, 5); sBasic->Add(m_RenderToMainWindow, wxGBPosition(1, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_StretchToFit, wxGBPosition(2, 0), wxGBSpan(1, 3), wxALL, 5); sBasic->Add(m_AutoScale, wxGBPosition(2, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_KeepAR43, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5); sBasic->Add(m_NativeResolution, wxGBPosition(3, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_KeepAR169, wxGBPosition(3, 1), wxGBSpan(1, 1), wxALL, 5); sBasic->Add(m_UseXFB, wxGBPosition(4, 0), wxGBSpan(1, 3), wxALL, 5);
sBasic->Add(m_Crop, wxGBPosition(3, 2), wxGBSpan(1, 1), wxALL, 5); sBasic->Add(m_KeepAR43, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_KeepAR169, wxGBPosition(5, 1), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(m_Crop, wxGBPosition(5, 2), wxGBSpan(1, 1), wxALL, 5);
// Because of the ifdef here we need this variable for the row number // Because of the ifdef here we need this variable for the row number
int Row = 4; int Row = 6;
#ifndef _WIN32 #ifndef _WIN32
sBasic->Add(m_HideCursor, wxGBPosition(Row++, 0), wxGBSpan(1, 3), wxALL, 5); sBasic->Add(m_HideCursor, wxGBPosition(Row++, 0), wxGBSpan(1, 3), wxALL, 5);
#endif #endif
@ -255,8 +254,6 @@ void ConfigDialog::CreateGUIControls()
sBasic->Add(m_FullscreenCB, wxGBPosition(Row++, 1), wxGBSpan(1, 1), wxALL, 5); sBasic->Add(m_FullscreenCB, wxGBPosition(Row++, 1), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(WMText, wxGBPosition(Row, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL, 5); sBasic->Add(WMText, wxGBPosition(Row, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL, 5);
sBasic->Add(m_WindowResolutionCB, wxGBPosition(Row++, 1), wxGBSpan(1, 1), wxALL, 5); sBasic->Add(m_WindowResolutionCB, wxGBPosition(Row++, 1), wxGBSpan(1, 1), wxALL, 5);
sBasic->Add(BEText, wxGBPosition(Row, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL, 5);
sBasic->Add(m_RenderBackend, wxGBPosition(Row++, 1), wxGBSpan(1, 1), wxALL, 5);
sbBasic->Add(sBasic); sbBasic->Add(sBasic);
sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5); sGeneral->Add(sbBasic, 0, wxEXPAND|wxALL, 5);
@ -293,8 +290,6 @@ void ConfigDialog::CreateGUIControls()
// Render // Render
sbRendering = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Rendering")); sbRendering = new wxStaticBoxSizer(wxVERTICAL, m_PageAdvanced, wxT("Rendering"));
m_UseXFB = new wxCheckBox(m_PageAdvanced, ID_USEXFB, wxT("Use External Framebuffer (XFB)"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_UseXFB->SetValue(g_Config.bUseXFB);
m_Wireframe = new wxCheckBox(m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); m_Wireframe = new wxCheckBox(m_PageAdvanced, ID_WIREFRAME, wxT("Enable Wireframe"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
m_Wireframe->SetValue(g_Config.bWireFrame); m_Wireframe->SetValue(g_Config.bWireFrame);
m_Wireframe->Enable(true); m_Wireframe->Enable(true);
@ -378,10 +373,9 @@ void ConfigDialog::CreateGUIControls()
wxBoxSizer *sRenderBoxRow1 = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *sRenderBoxRow1 = new wxBoxSizer(wxHORIZONTAL);
sRendering = new wxGridBagSizer(0, 0); sRendering = new wxGridBagSizer(0, 0);
sRendering->Add(m_UseXFB, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5); sRendering->Add(m_Wireframe, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALL, 5);
sRendering->Add(m_Wireframe, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5); sRendering->Add(m_DisableLighting, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALL, 5);
sRendering->Add(m_DisableLighting, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALL, 5); sRendering->Add(m_DisableTexturing, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALL, 5);
sRendering->Add(m_DisableTexturing, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5);
sRenderBoxRow1->Add(sRendering, 0, wxALL|wxEXPAND, 5); sRenderBoxRow1->Add(sRendering, 0, wxALL|wxEXPAND, 5);
wxStaticBoxSizer *sSBox = new wxStaticBoxSizer(m_StaticBox_EFB, wxVERTICAL); wxStaticBoxSizer *sSBox = new wxStaticBoxSizer(m_StaticBox_EFB, wxVERTICAL);
wxBoxSizer *sStrip1 = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer *sStrip1 = new wxBoxSizer(wxHORIZONTAL);
@ -431,8 +425,15 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_RENDERTOMAINWINDOW: case ID_RENDERTOMAINWINDOW:
g_Config.renderToMainframe = m_RenderToMainWindow->IsChecked(); g_Config.renderToMainframe = m_RenderToMainWindow->IsChecked();
break; break;
case ID_STRETCHTOFIT: case ID_NATIVERESOLUTION:
g_Config.bStretchToFit = m_StretchToFit->IsChecked(); g_Config.bNativeResolution = m_NativeResolution->IsChecked();
break;
case ID_USEXFB:
g_Config.bUseXFB = m_UseXFB->IsChecked();
break;
case ID_AUTOSCALE:
g_Config.bAutoScale = m_AutoScale->IsChecked();
break; break;
case ID_KEEPAR_4_3: case ID_KEEPAR_4_3:
g_Config.bKeepAR43 = m_KeepAR43->IsChecked(); g_Config.bKeepAR43 = m_KeepAR43->IsChecked();
@ -447,6 +448,7 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_CROP: case ID_CROP:
g_Config.bCrop = m_Crop->IsChecked(); g_Config.bCrop = m_Crop->IsChecked();
break; break;
#ifndef _WIN32 #ifndef _WIN32
case ID_HIDECURSOR: case ID_HIDECURSOR:
g_Config.bHideCursor = m_HideCursor->IsChecked(); g_Config.bHideCursor = m_HideCursor->IsChecked();
@ -458,9 +460,6 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_WINDOWRESOLUTIONCB: case ID_WINDOWRESOLUTIONCB:
strcpy(g_Config.iWindowedRes, m_WindowResolutionCB->GetValue().mb_str() ); strcpy(g_Config.iWindowedRes, m_WindowResolutionCB->GetValue().mb_str() );
break; break;
case ID_RENDERBACKEND:
strcpy(g_Config.iBackend, m_RenderBackend->GetValue().mb_str());
break;
case ID_FORCEFILTERING: case ID_FORCEFILTERING:
g_Config.bForceFiltering = m_ForceFiltering->IsChecked(); g_Config.bForceFiltering = m_ForceFiltering->IsChecked();
break; break;
@ -498,9 +497,6 @@ void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event)
g_Config.bTexFmtOverlayCenter = m_TexFmtCenter->IsChecked(); g_Config.bTexFmtOverlayCenter = m_TexFmtCenter->IsChecked();
TextureMngr::Invalidate(false); TextureMngr::Invalidate(false);
break; break;
case ID_USEXFB:
g_Config.bUseXFB = m_UseXFB->IsChecked();
break;
case ID_WIREFRAME: case ID_WIREFRAME:
g_Config.bWireFrame = m_Wireframe->IsChecked(); g_Config.bWireFrame = m_Wireframe->IsChecked();
break; break;
@ -532,12 +528,14 @@ void ConfigDialog::AdvancedSettingsChanged(wxCommandEvent& event)
case ID_SAFETEXTURECACHE: case ID_SAFETEXTURECACHE:
g_Config.bSafeTextureCache = m_SafeTextureCache->IsChecked(); g_Config.bSafeTextureCache = m_SafeTextureCache->IsChecked();
break; break;
// Extented frame buffer
// External frame buffer
case ID_RADIO_COPYEFBTORAM: case ID_RADIO_COPYEFBTORAM:
TextureMngr::ClearRenderTargets(); TextureMngr::ClearRenderTargets();
g_Config.bCopyEFBToRAM = true; g_Config.bCopyEFBToRAM = true;
break; break;
case ID_RADIO_COPYEFBTOGL: case ID_RADIO_COPYEFBTOGL:
TextureMngr::ClearRenderTargets();
g_Config.bCopyEFBToRAM = false; g_Config.bCopyEFBToRAM = false;
break; break;
case ID_BLENDSTATS: case ID_BLENDSTATS:
@ -563,11 +561,14 @@ void ConfigDialog::TexturePathChange(wxFileDirPickerEvent& event)
void ConfigDialog::UpdateGUI() void ConfigDialog::UpdateGUI()
{ {
// This option is only compatible with the Strech To Fit option
m_KeepAR43->Enable(g_Config.bStretchToFit);
m_KeepAR169->Enable(g_Config.bStretchToFit);
// This is only used together with the aspect ratio options // This is only used together with the aspect ratio options
m_Crop->Enable(g_Config.bStretchToFit && (g_Config.bKeepAR43 || g_Config.bKeepAR169)); m_Crop->Enable(g_Config.bKeepAR43 || g_Config.bKeepAR169);
if (g_Config.bUseXFB) {
// XFB looks much better if the copy comes from native resolution.
g_Config.bNativeResolution = true;
m_NativeResolution->SetValue(true);
}
m_AutoScale->Enable(!g_Config.bUseXFB);
// These options are for the separate rendering window // These options are for the separate rendering window
m_Fullscreen->Enable(!g_Config.renderToMainframe); m_Fullscreen->Enable(!g_Config.renderToMainframe);

View File

@ -45,7 +45,6 @@ class ConfigDialog : public wxDialog
void AddFSReso(char *reso); void AddFSReso(char *reso);
void AddWindowReso(char *reso); void AddWindowReso(char *reso);
void AddRenderBackend(const char *backend);
void AddAAMode(int mode); void AddAAMode(int mode);
void CreateGUIControls(); void CreateGUIControls();
@ -77,16 +76,16 @@ class ConfigDialog : public wxDialog
wxPanel *m_PageAdvanced; wxPanel *m_PageAdvanced;
wxCheckBox *m_Fullscreen; wxCheckBox *m_Fullscreen;
wxCheckBox *m_RenderToMainWindow; wxCheckBox *m_RenderToMainWindow;
wxCheckBox *m_StretchToFit; wxCheckBox *m_NativeResolution;
wxCheckBox *m_KeepAR43, *m_KeepAR169, *m_Crop; wxCheckBox *m_KeepAR43, *m_KeepAR169, *m_Crop;
wxCheckBox *m_UseXFB;
wxCheckBox *m_AutoScale;
#ifndef _WIN32 #ifndef _WIN32
wxCheckBox *m_HideCursor; wxCheckBox *m_HideCursor;
#endif #endif
wxComboBox *m_FullscreenCB; wxComboBox *m_FullscreenCB;
wxArrayString arrayStringFor_WindowResolutionCB; wxArrayString arrayStringFor_WindowResolutionCB;
wxComboBox *m_WindowResolutionCB; wxComboBox *m_WindowResolutionCB;
wxArrayString arrayStringFor_RenderBackend;
wxComboBox *m_RenderBackend;
wxCheckBox *m_ForceFiltering; // advanced wxCheckBox *m_ForceFiltering; // advanced
wxChoice *m_MaxAnisotropyCB; wxChoice *m_MaxAnisotropyCB;
@ -99,7 +98,6 @@ class ConfigDialog : public wxDialog
wxCheckBox *m_ProjStats; wxCheckBox *m_ProjStats;
wxCheckBox *m_TexFmtOverlay; wxCheckBox *m_TexFmtOverlay;
wxCheckBox *m_TexFmtCenter; wxCheckBox *m_TexFmtCenter;
wxCheckBox *m_UseXFB;
wxCheckBox *m_Wireframe; wxCheckBox *m_Wireframe;
wxCheckBox *m_DisableLighting; wxCheckBox *m_DisableLighting;
wxCheckBox *m_DisableTexturing; wxCheckBox *m_DisableTexturing;
@ -128,15 +126,16 @@ class ConfigDialog : public wxDialog
ID_FULLSCREEN, ID_FULLSCREEN,
ID_RENDERTOMAINWINDOW, ID_RENDERTOMAINWINDOW,
ID_STRETCHTOFIT, ID_NATIVERESOLUTION,
ID_KEEPAR_4_3, ID_KEEPAR_16_9, ID_CROP, ID_KEEPAR_4_3, ID_KEEPAR_16_9, ID_CROP,
ID_USEXFB,
ID_AUTOSCALE,
ID_HIDECURSOR, ID_HIDECURSOR,
ID_FSTEXT, ID_FSTEXT,
ID_FULLSCREENCB, ID_FULLSCREENCB,
ID_WMTEXT, ID_WMTEXT,
ID_WINDOWRESOLUTIONCB, ID_WINDOWRESOLUTIONCB,
ID_BETEXT,
ID_RENDERBACKEND,
ID_FORCEFILTERING, ID_FORCEFILTERING,
ID_MAXANISOTROPY, ID_MAXANISOTROPY,
@ -151,7 +150,6 @@ class ConfigDialog : public wxDialog
ID_TEXFMTOVERLAY, ID_TEXFMTOVERLAY,
ID_TEXFMTCENTER, ID_TEXFMTCENTER,
ID_USEXFB,
ID_WIREFRAME, ID_WIREFRAME,
ID_DISABLELIGHTING, ID_DISABLELIGHTING,
ID_DISABLETEXTURING, ID_DISABLETEXTURING,

View File

@ -152,7 +152,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader()
return pShaderLast; return pShaderLast;
} }
void PixelShaderCache::Cleanup() void PixelShaderCache::ProgressiveCleanup()
{ {
PSCache::iterator iter = pshaders.begin(); PSCache::iterator iter = pshaders.begin();
while (iter != pshaders.end()) { while (iter != pshaders.end()) {
@ -168,14 +168,14 @@ void PixelShaderCache::Cleanup()
else else
iter++; iter++;
} }
SETSTAT(stats.numPixelShadersAlive,(int)pshaders.size()); SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
} }
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
{ {
char stropt[64]; char stropt[128];
sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions); sprintf(stropt, "MaxLocalParams=32,NumInstructionSlots=%d", s_nMaxPixelInstructions);
const char* opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL};
CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts);
if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) { if (!cgIsProgram(tempprog) || cgGetError() != CG_NO_ERROR) {
ERROR_LOG(VIDEO, "Failed to create ps %s:\n", cgGetLastListing(g_cgcontext)); ERROR_LOG(VIDEO, "Failed to create ps %s:\n", cgGetLastListing(g_cgcontext));
@ -183,18 +183,20 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
return false; return false;
} }
// This looks evil - we modify the program through the const char * we got from cgGetProgramString!
// It SHOULD not have any nasty side effects though - but you never know...
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
char *plocal = strstr(pcompiledprog, "program.local"); char *plocal = strstr(pcompiledprog, "program.local");
while (plocal != NULL) { while (plocal != NULL) {
const char* penv = " program.env"; const char *penv = " program.env";
memcpy(plocal, penv, 13); memcpy(plocal, penv, 13);
plocal = strstr(plocal+13, "program.local"); plocal = strstr(plocal+13, "program.local");
} }
if (Renderer::IsUsingATIDrawBuffers()) { if (Renderer::IsUsingATIDrawBuffers()) {
// sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards // Sometimes compilation can use ARB_draw_buffers, which would fail for ATI cards.
// replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers. // Replace the three characters ARB with ATI. TODO - check whether this is fixed in modern ATI drivers.
char* poptions = strstr(pcompiledprog, "ARB_draw_buffers"); char *poptions = strstr(pcompiledprog, "ARB_draw_buffers");
if (poptions != NULL) { if (poptions != NULL) {
poptions[0] = 'A'; poptions[0] = 'A';
poptions[1] = 'T'; poptions[1] = 'T';
@ -202,9 +204,9 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
} }
} }
glGenProgramsARB( 1, &ps.glprogid ); glGenProgramsARB(1, &ps.glprogid);
glBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ps.glprogid ); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ps.glprogid);
glProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
GLenum err = GL_NO_ERROR; GLenum err = GL_NO_ERROR;
GL_REPORT_ERROR(); GL_REPORT_ERROR();
@ -214,7 +216,6 @@ bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrpr
} }
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
// printf("Compiled pixel shader %i\n", ps.glprogid);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
ps.strprog = pstrprogram; ps.strprog = pstrprogram;

View File

@ -53,7 +53,7 @@ class PixelShaderCache
public: public:
static void Init(); static void Init();
static void Cleanup(); static void ProgressiveCleanup();
static void Shutdown(); static void Shutdown();
static FRAGMENTSHADER* GetShader(); static FRAGMENTSHADER* GetShader();

View File

@ -41,6 +41,8 @@
#include "VertexShaderGen.h" #include "VertexShaderGen.h"
#include "PixelShaderCache.h" #include "PixelShaderCache.h"
#include "PixelShaderManager.h" #include "PixelShaderManager.h"
#include "VertexShaderCache.h"
#include "VertexShaderManager.h"
#include "VertexLoaderManager.h" #include "VertexLoaderManager.h"
#include "VertexLoader.h" #include "VertexLoader.h"
#include "XFB.h" #include "XFB.h"
@ -82,14 +84,23 @@ static GLuint s_ZBufferTarget = 0;
static bool s_bATIDrawBuffers = false; static bool s_bATIDrawBuffers = false;
static bool s_bHaveStencilBuffer = false; static bool s_bHaveStencilBuffer = false;
static bool s_bHaveFramebufferBlit = false;
static bool s_bScreenshot = false; static volatile bool s_bScreenshot = false;
static Common::CriticalSection s_criticalScreenshot; static Common::CriticalSection s_criticalScreenshot;
static std::string s_sScreenshotName; static std::string s_sScreenshotName;
static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal; static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal;
bool g_bBlendSeparate = false; bool g_bBlendSeparate = false;
int frameCount; int frameCount;
static int s_fps = 0;
// These STAY CONSTANT during execution, no matter how much you resize the game window.
static int s_targetwidth; // Size of render buffer FBO.
static int s_targetheight;
static u32 s_blendMode;
void HandleCgError(CGcontext ctx, CGerror err, void *appdata); void HandleCgError(CGcontext ctx, CGerror err, void *appdata);
@ -110,57 +121,57 @@ static const GLenum glDestFactors[8] = {
GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA
}; };
static u32 s_blendMode;
bool Renderer::Init() bool Renderer::Init()
{ {
bool bSuccess = true; bool bSuccess = true;
int numvertexattribs = 0; s_blendMode = 0;
GLint numvertexattribs = 0;
GLenum err = GL_NO_ERROR; GLenum err = GL_NO_ERROR;
g_cgcontext = cgCreateContext(); g_cgcontext = cgCreateContext();
cgGetError(); cgGetError();
cgSetErrorHandler(HandleCgError, NULL); cgSetErrorHandler(HandleCgError, NULL);
// fill the opengl extension map // Look for required extensions.
const char* ptoken = (const char*)glGetString(GL_EXTENSIONS); const char *ptoken = (const char*)glGetString(GL_EXTENSIONS);
if (ptoken == NULL) return false; if (!ptoken)
{
PanicAlert("Failed to get OpenGL extension string. Do you have OpenGL drivers installed?");
return false;
}
INFO_LOG(VIDEO, "Supported OpenGL Extensions:\n"); INFO_LOG(VIDEO, "Supported OpenGL Extensions:\n");
INFO_LOG(VIDEO, ptoken); // write to the log file INFO_LOG(VIDEO, ptoken); // write to the log file
INFO_LOG(VIDEO, "\n"); INFO_LOG(VIDEO, "\n");
if (GLEW_EXT_blend_func_separate && GLEW_EXT_blend_equation_separate) if (GLEW_EXT_blend_func_separate && GLEW_EXT_blend_equation_separate)
g_bBlendSeparate = true; g_bBlendSeparate = true;
// Checks if it ONLY has the ATI_draw_buffers extension, some have both
//Checks if it ONLY has the ATI_draw_buffers extension, some have both
if (GLEW_ATI_draw_buffers && !GLEW_ARB_draw_buffers) if (GLEW_ATI_draw_buffers && !GLEW_ARB_draw_buffers)
s_bATIDrawBuffers = true; s_bATIDrawBuffers = true;
s_bFullscreen = g_Config.bFullscreen; s_bFullscreen = g_Config.bFullscreen;
if (glewInit() != GLEW_OK) { glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &numvertexattribs);
ERROR_LOG(VIDEO, "glewInit() failed!\nDoes your video card support OpenGL 2.x?");
return false;
}
if (!GLEW_EXT_framebuffer_object) {
ERROR_LOG(VIDEO, "*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\nDoes your video card support OpenGL 2.x?");
bSuccess = false;
}
if (!GLEW_EXT_secondary_color) {
ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\nDoes your video card support OpenGL 2.x?");
bSuccess = false;
}
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint *)&numvertexattribs);
if (numvertexattribs < 11) { if (numvertexattribs < 11) {
ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\nDoes your video card support OpenGL 2.x?", numvertexattribs); ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\nDoes your video card support OpenGL 2.x?", numvertexattribs);
bSuccess = false; bSuccess = false;
} }
// Init extension support.
if (glewInit() != GLEW_OK) {
ERROR_LOG(VIDEO, "glewInit() failed!\nDoes your video card support OpenGL 2.x?");
return false;
}
if (!GLEW_EXT_framebuffer_object) {
ERROR_LOG(VIDEO, "*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\nDoes your video card support OpenGL 2.x?");
bSuccess = false;
}
if (!GLEW_EXT_secondary_color) {
ERROR_LOG(VIDEO, "*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\nDoes your video card support OpenGL 2.x?");
bSuccess = false;
}
s_bHaveFramebufferBlit = GLEW_EXT_framebuffer_blit ? true : false;
if (!bSuccess) if (!bSuccess)
return false; return false;
@ -186,7 +197,6 @@ bool Renderer::Init()
if (max_texture_size < 1024) { if (max_texture_size < 1024) {
ERROR_LOG(VIDEO, "GL_MAX_TEXTURE_SIZE too small at %i - must be at least 1024", max_texture_size); ERROR_LOG(VIDEO, "GL_MAX_TEXTURE_SIZE too small at %i - must be at least 1024", max_texture_size);
} }
GL_REPORT_ERROR(); GL_REPORT_ERROR();
if (err != GL_NO_ERROR) bSuccess = false; if (err != GL_NO_ERROR) bSuccess = false;
@ -204,16 +214,17 @@ bool Renderer::Init()
// The size of the framebuffer targets should really NOT be the size of the OpenGL viewport. // The size of the framebuffer targets should really NOT be the size of the OpenGL viewport.
// The EFB is larger than 640x480 - in fact, it's 640x528, give or take a couple of lines. // The EFB is larger than 640x480 - in fact, it's 640x528, give or take a couple of lines.
// So the below is wrong. // So the below is wrong.
int nBackbufferWidth = (int)OpenGL_GetWidth(); // This should really be grabbed from config rather than from OpenGL.
int nBackbufferHeight = (int)OpenGL_GetHeight(); s_targetwidth = (int)OpenGL_GetBackbufferWidth();
s_targetheight = (int)OpenGL_GetBackbufferHeight();
// Create the framebuffer target // Create the framebuffer target texture
glGenTextures(1, (GLuint *)&s_RenderTarget); glGenTextures(1, (GLuint *)&s_RenderTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget);
// Setup the texture params // Setup the texture params
// initialize to default // initialize to default
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (glGetError() != GL_NO_ERROR) { if (glGetError() != GL_NO_ERROR) {
@ -226,16 +237,14 @@ bool Renderer::Init()
GL_REPORT_ERROR(); GL_REPORT_ERROR();
int nMaxMRT = 0; GLint nMaxMRT = 0;
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, (GLint *)&nMaxMRT); glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, &nMaxMRT);
if (nMaxMRT > 1) if (nMaxMRT > 1)
{ {
// create zbuffer target // Create zbuffer target.
glGenTextures(1, (GLuint *)&s_ZBufferTarget); glGenTextures(1, (GLuint *)&s_ZBufferTarget);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, nBackbufferWidth, nBackbufferHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, s_targetwidth, s_targetheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (glGetError() != GL_NO_ERROR) { if (glGetError() != GL_NO_ERROR) {
@ -248,13 +257,12 @@ bool Renderer::Init()
} }
// create the depth buffer // create the depth buffer
glGenRenderbuffersEXT(1, (GLuint *)&s_DepthTarget); glGenRenderbuffersEXT(1, &s_DepthTarget);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, nBackbufferWidth, nBackbufferHeight); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_targetwidth, s_targetheight);
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
{ {
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, nBackbufferWidth, nBackbufferHeight); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, s_targetwidth, s_targetheight);
s_bHaveStencilBuffer = false; s_bHaveStencilBuffer = false;
} }
else else
@ -264,7 +272,7 @@ bool Renderer::Init()
GL_REPORT_ERROR(); GL_REPORT_ERROR();
// set as render targets // Select our render and depth targets as render targets.
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, s_RenderTarget, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget);
@ -283,10 +291,7 @@ bool Renderer::Init()
} }
if (s_ZBufferTarget == 0) if (s_ZBufferTarget == 0)
ERROR_LOG(VIDEO, "disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT); ERROR_LOG(VIDEO, "Disabling ztarget MRT feature (max MRT = %d)\n", nMaxMRT);
// Why is this left here?
//glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
nZBufferRender = 0; nZBufferRender = 0;
@ -313,17 +318,17 @@ bool Renderer::Init()
cgGLSetOptimalOptions(g_cgvProf); cgGLSetOptimalOptions(g_cgvProf);
cgGLSetOptimalOptions(g_cgfProf); cgGLSetOptimalOptions(g_cgfProf);
//ERROR_LOG(VIDEO, "max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf)); INFO_LOG(VIDEO, "Max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf));
int nenvvertparams, nenvfragparams, naddrregisters[2]; int nenvvertparams, nenvfragparams, naddrregisters[2];
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams);
glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]); glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]);
DEBUG_LOG(VIDEO, "max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams); DEBUG_LOG(VIDEO, "Max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams);
DEBUG_LOG(VIDEO, "max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]); DEBUG_LOG(VIDEO, "Max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]);
if (nenvvertparams < 238) if (nenvvertparams < 238)
ERROR_LOG(VIDEO, "not enough vertex shader environment constants!!\n"); ERROR_LOG(VIDEO, "Not enough vertex shader environment constants!!\n");
#ifndef _DEBUG #ifndef _DEBUG
cgGLSetDebugMode(GL_FALSE); cgGLSetDebugMode(GL_FALSE);
@ -342,6 +347,7 @@ bool Renderer::Init()
XFB_Init(); XFB_Init();
return glGetError() == GL_NO_ERROR && bSuccess; return glGetError() == GL_NO_ERROR && bSuccess;
} }
void Renderer::Shutdown(void) void Renderer::Shutdown(void)
{ {
delete s_pfont; delete s_pfont;
@ -421,15 +427,25 @@ bool Renderer::InitializeGL()
// ------------------------ // ------------------------
int Renderer::GetTargetWidth() int Renderer::GetTargetWidth()
{ {
return (g_Config.bStretchToFit ? 640 : (int)OpenGL_GetWidth()); return (g_Config.bNativeResolution ? 640 : s_targetwidth);
} }
int Renderer::GetTargetHeight() int Renderer::GetTargetHeight()
{ {
return (g_Config.bStretchToFit ? 480 : (int)OpenGL_GetHeight()); return (g_Config.bNativeResolution ? 480 : s_targetheight);
} }
/////////////////////////////
float Renderer::GetTargetScaleX()
{
return (float)GetTargetWidth() / 640.0f;
}
float Renderer::GetTargetScaleY()
{
return (float)GetTargetHeight() / 480.0f;
}
/////////////////////////////
void Renderer::SetRenderTarget(GLuint targ) void Renderer::SetRenderTarget(GLuint targ)
{ {
@ -573,8 +589,8 @@ bool Renderer::SetScissorRect()
{ {
int xoff = bpmem.scissorOffset.x * 2 - 342; int xoff = bpmem.scissorOffset.x * 2 - 342;
int yoff = bpmem.scissorOffset.y * 2 - 342; int yoff = bpmem.scissorOffset.y * 2 - 342;
float MValueX = OpenGL_GetXmax(); float MValueX = GetTargetScaleX();
float MValueY = OpenGL_GetYmax(); float MValueY = GetTargetScaleY();
float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0 float rc_left = (float)bpmem.scissorTL.x - xoff - 342; // left = 0
rc_left *= MValueX; rc_left *= MValueX;
if (rc_left < 0) rc_left = 0; if (rc_left < 0) rc_left = 0;
@ -660,11 +676,11 @@ void Renderer::FlushZBufferAlphaToTarget()
// TODO: This code should not have to bother with stretchtofit checking - // TODO: This code should not have to bother with stretchtofit checking -
// all necessary scale initialization should be done elsewhere. // all necessary scale initialization should be done elsewhere.
// TODO: Investigate BlitFramebufferEXT. // TODO: Investigate BlitFramebufferEXT.
if (g_Config.bStretchToFit) if (g_Config.bNativeResolution)
{ {
//TODO: Do Correctly in a bit //TODO: Do Correctly in a bit
float FactorW = 640.f / (float)OpenGL_GetWidth(); float FactorW = 640.f / (float)OpenGL_GetBackbufferWidth();
float FactorH = 480.f / (float)OpenGL_GetHeight(); float FactorH = 480.f / (float)OpenGL_GetBackbufferHeight();
float Max = (FactorW < FactorH) ? FactorH : FactorW; float Max = (FactorW < FactorH) ? FactorH : FactorW;
float Temp = 1.0f / Max; float Temp = 1.0f / Max;
@ -763,181 +779,48 @@ Renderer::RenderMode Renderer::GetRenderMode()
return s_RenderMode; return s_RenderMode;
} }
void ComputeBackbufferRectangle(TRectangle *rc)
//////////////////////////////////////////////////////////////////////////////////////
// This function has the final picture if the XFB functions are not used. We adjust the aspect ratio here.
// ----------------------
void Renderer::Swap(const TRectangle& rc)
{ {
OpenGL_Update(); // just updates the render window position and the backbuffer size
DVSTARTPROFILE();
Renderer::SetRenderMode(Renderer::RM_Normal);
#if 0
// Blit the FBO to do Anti-Aliasing
// Not working?
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_uFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
glBlitFramebufferEXT(0, 0, 640, 480, 0, 0, OpenGL_GetWidth(), OpenGL_GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
#else
// render to the real buffer now
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// GLViewPort variables // GLViewPort variables
// ------------------ // ------------------
/* Work with float values for the XFB supplement and aspect ratio functions. These are default // Work with float values for the XFB supplement and aspect ratio functions. These are default
values that are used if the XFB supplement and the keep aspect ratio function are unused */ // values that are used if the XFB supplement and the keep aspect ratio function are unused.
float FloatGLWidth = (float)OpenGL_GetWidth(); float FloatGLWidth = (float)OpenGL_GetBackbufferWidth();
float FloatGLHeight = (float)OpenGL_GetHeight(); float FloatGLHeight = (float)OpenGL_GetBackbufferHeight();
float FloatXOffset = 0, FloatYOffset = 0; float FloatXOffset = 0;
// ------------------------------------- float FloatYOffset = 0;
// The rendering window size
const float WinWidth = FloatGLWidth;
const float WinHeight = FloatGLHeight;
// ----------------------------------------------------------------------- // Handle aspect ratio.
// XFB supplement, fix the black borders problem if (g_Config.bKeepAR43 || g_Config.bKeepAR169)
// ------------------
/* I'm limiting it to the stretch to fit option because I don't know how the other mode works. The reason
I don't allow this option together with UseXFB is that they are supplements and the XFB function
should be able to produce the same result */
if(g_Config.bStretchToFit && !g_Config.bUseXFB)
{ {
// The rendering window size
float WinWidth = (float)OpenGL_GetWidth();
float WinHeight = (float)OpenGL_GetHeight();
// The fraction of the screen that the image occupies
// Rc.right and rc.bottom is the original picture pixel size
/* There is a +1 in Rc (earlier called multirc, the input to this function), but these
adjustments seems to work better without it. */
float WidthRatio = (float)(rc.right - 1) / 640.0f;
float HeightRatio = (float)(rc.bottom - 1) / 480.0f;
// The pixel size of the image on the screen, adjusted for the actual window size
float OldWidth = WidthRatio * (float)WinWidth;
float OldHeight = HeightRatio * (float)WinHeight;
// The adjusted width and height
FloatGLWidth = ceil((float)WinWidth / WidthRatio);
FloatGLHeight = ceil((float)WinHeight / HeightRatio);
// The width and height deficit in actual pixels
float WidthDeficit = (float)WinWidth - OldWidth;
float HeightDeficit = (float)WinHeight - OldHeight;
// The picture will be drawn from the bottom so we need this YOffset
// The X-axis needs no adjustment because the picture begins from the left
FloatYOffset = -HeightDeficit / HeightRatio;
// -----------------------------------------------------------------------
// Logging
// ------------------
/*
Console::ClearScreen();
Console::Print("Bpmem L:%i T:%i X:%i Y:%i\n", bpmem.copyTexSrcXY.x, bpmem.copyTexSrcXY.y, bpmem.copyTexSrcWH.x, bpmem.copyTexSrcWH.y);
Console::Print("Input Left:%i Top:%i Right:%i Bottom:%i\n", rc.left, rc.top, rc.right, rc.bottom);
Console::Print("Old picture: Width[%1.2f]:%4.0f Height[%1.2f]:%4.0f\n", WidthRatio, OldWidth, HeightRatio, OldHeight);
Console::Print("New picture: Width[%1.2f]:%4.0f Height[%1.2f]:%4.0f YOffset:%4.0f YDeficit:%4.0f\n", WidthRatio, WinWidth, HeightRatio, WinHeight, FloatYOffset, HeightDeficit);
Console::Print("----------------------------------------------------------------\n");
*/
// ------------------------------
}
// ------------------------------
// -----------------------------------------------------------------------
/* Keep aspect ratio at 4:3. This may be interesting if you for example have a 5:4 screen but don't like
the stretching, and would rather have a letterbox. */
// Output: GLWidth, GLHeight, XOffset, YOffset
// ------------------
// The rendering window size
float WinWidth = (float)OpenGL_GetWidth();
float WinHeight = (float)OpenGL_GetHeight();
// The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio // The rendering window aspect ratio as a proportion of the 4:3 or 16:9 ratio
float Ratio = WinWidth / WinHeight / (g_Config.bKeepAR43 ? (4.0f / 3.0f) : (16.0f / 9.0f)); float Ratio = (WinWidth / WinHeight) / (g_Config.bKeepAR43 ? (4.0f / 3.0f) : (16.0f / 9.0f));
float wAdj, hAdj;
// Actual pixel size of the picture after adjustment
float PictureWidth = WinWidth, PictureHeight = WinHeight;
// This function currently only works together with the Stretch To Fit option
if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bStretchToFit)
{
// Check if height or width is the limiting factor. If ratio > 1 the picture is to wide and have to limit the width. // Check if height or width is the limiting factor. If ratio > 1 the picture is to wide and have to limit the width.
if (Ratio > 1) if (Ratio > 1)
{ {
// ------------------------------------------------ // Scale down and center in the X direction.
// Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen FloatGLWidth /= Ratio;
// ---------------- FloatXOffset = (WinWidth - FloatGLWidth) / 2.0f;
wAdj = Ratio;
hAdj = 1.0;
FloatGLWidth = FloatGLWidth / wAdj;
FloatGLHeight = FloatGLHeight / hAdj;
// --------------------
// ------------------------------------------------
// Calculate the new X offset
// ----------------
// The picture width
PictureWidth = WinWidth / Ratio;
// Move the left of the picture to the middle of the screen
FloatXOffset = FloatXOffset + WinWidth / 2.0f;
// Then remove half the picture height to move it to the horizontal center
FloatXOffset = FloatXOffset - PictureWidth / 2.0f;
// --------------------
} }
// The window is to high, we have to limit the height // The window is too high, we have to limit the height
else else
{ {
// ------------------------------------------------ // Scale down and center in the Y direction.
// Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen FloatGLHeight *= Ratio;
// ---------------- FloatYOffset = FloatYOffset + (WinHeight - FloatGLHeight) / 2.0f;
// Invert the ratio to make it > 1
Ratio = 1.0f / Ratio;
wAdj = 1.0f;
hAdj = Ratio;
FloatGLWidth = FloatGLWidth / wAdj;
FloatGLHeight = FloatGLHeight / hAdj;
// --------------------
// ------------------------------------------------
// Calculate the new Y offset
// ----------------
// The picture height
PictureHeight = WinHeight / Ratio;
// Keep the picture on the bottom of the screen, this is needed because YOffset may not be 0 here
FloatYOffset = FloatYOffset / hAdj;
// Move the bottom of the picture to the middle of the screen
FloatYOffset = FloatYOffset + WinHeight / 2.0f;
// Then remove half the picture height to move it to the vertical center
FloatYOffset = FloatYOffset - PictureHeight / 2.0f;
// --------------------
} }
// -----------------------------------------------------------------------
// Logging
// ------------------
/*
Console::Print("Screen Width:%4.0f Height:%4.0f Ratio:%1.2f\n", WinWidth, WinHeight, Ratio);
Console::Print("GL Width:%4.1f Height:%4.1f\n", FloatGLWidth, FloatGLHeight);
Console::Print("Picture Width:%4.1f Height:%4.1f YOffset:%4.0f\n", PictureWidth, PictureHeight, FloatYOffset);
Console::Print("----------------------------------------------------------------\n");
*/
// ------------------------------
} }
// -------------------------------------
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
/* Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. */ /* Crop the picture from 4:3 to 5:4 or from 16:9 to 16:10. */
// Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset // Output: FloatGLWidth, FloatGLHeight, FloatXOffset, FloatYOffset
// ------------------ // ------------------
if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bStretchToFit && g_Config.bCrop) if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bCrop)
{ {
float Ratio = g_Config.bKeepAR43 ? ((4.0 / 3.0) / (5.0 / 4.0)) : (((16.0 / 9.0) / (16.0 / 10.0))); float Ratio = g_Config.bKeepAR43 ? ((4.0 / 3.0) / (5.0 / 4.0)) : (((16.0 / 9.0) / (16.0 / 10.0)));
// The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted) // The width and height we will add (calculate this before FloatGLWidth and FloatGLHeight is adjusted)
@ -946,47 +829,47 @@ void Renderer::Swap(const TRectangle& rc)
// The new width and height // The new width and height
FloatGLWidth = FloatGLWidth * Ratio; FloatGLWidth = FloatGLWidth * Ratio;
FloatGLHeight = FloatGLHeight * Ratio; FloatGLHeight = FloatGLHeight * Ratio;
// Wee need this adjustment to, the -6 adjustment was needed to never show any pixels outside the actual picture // We need this adjustment too, the -6 adjustment was needed to never show any pixels outside the actual picture
// The result in offset in actual pixels is only around 1 or 2 pixels in a 1280 x 1024 resolution. In 1280 x 1024 the // The result in offset in actual pixels is only around 1 or 2 pixels in a 1280 x 1024 resolution. In 1280 x 1024 the
// picture is only about 2 to 4 pixels (1 up and 1 down for example) to big to produce a minimal margin // picture is only about 2 to 4 pixels (1 up and 1 down for example) to big to produce a minimal margin
// of error, while rather having a full screen and hiding one pixel, than having a one pixel black border. But it seems // of error, while rather having a full screen and hiding one pixel, than having a one pixel black border. But it seems
// to be just enough in all games I tried. // to be just enough in all games I tried.
float WidthRatio = ((float)rc.right - 6.0) / 640.0; float WidthRatio = ((float)FloatGLWidth - 6.0) / 640.0;
float HeightRatio = ((float)rc.bottom - 6.0) / 480.0; float HeightRatio = ((float)FloatGLHeight - 6.0) / 480.0;
// Adjust the X and Y offset // Adjust the X and Y offset
FloatXOffset = FloatXOffset - (IncreasedWidth / 2.0 / WidthRatio / Ratio); FloatXOffset = FloatXOffset - (IncreasedWidth / 2.0 / WidthRatio / Ratio);
FloatYOffset = FloatYOffset - (IncreasedHeight / 2.0 / HeightRatio / Ratio); FloatYOffset = FloatYOffset - (IncreasedHeight / 2.0 / HeightRatio / Ratio);
//Console::Print("Crop Ratio:%1.2f IncreasedHeight:%3.0f YOffset:%3.0f\n", Ratio, IncreasedHeight, FloatYOffset); //Console::Print("Crop Ratio:%1.2f IncreasedHeight:%3.0f YOffset:%3.0f\n", Ratio, IncreasedHeight, FloatYOffset);
} }
// -------------------------------------
// -----------------------------------------------------------------------
/* Adjustments to
FloatGLWidth
FloatGLHeight
XOffset
YOffset
are done. Calculate the new new windows width and height. */
// --------------------
int GLx = OpenGL_GetXoff(); // These two are zero
int GLy = OpenGL_GetYoff();
int GLWidth = ceil(FloatGLWidth);
int GLHeight = ceil(FloatGLHeight);
// Because there is no round() function we use round(float) = floor(float + 0.5) instead // Because there is no round() function we use round(float) = floor(float + 0.5) instead
int XOffset = floor(FloatXOffset + 0.5);
int YOffset = floor(FloatYOffset + 0.5); int YOffset = floor(FloatYOffset + 0.5);
int XOffset = floor(FloatXOffset+ 0.5); rc->left = XOffset;
// ------------------------------------- rc->top = YOffset;
rc->right = XOffset + ceil(FloatGLWidth);
rc->bottom = YOffset + ceil(FloatGLHeight);
}
//////////////////////////////////////////////////////////////////////////////////////
// This function has the final picture if the XFB functions are not used. We adjust the aspect ratio here.
// ----------------------
void Renderer::Swap(const TRectangle& rc)
{
OpenGL_Update(); // just updates the render window position and the backbuffer size
DVSTARTPROFILE();
// Update GLViewPort Renderer::SetRenderMode(Renderer::RM_Normal);
glViewport(
GLx + XOffset, // Blit the FBO to do Anti-Aliasing
GLy + YOffset, // Not working?
GLWidth, // glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, s_uFramebuffer);
GLHeight // glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
); // glBlitFramebufferEXT(0, 0, 640, 480, 0, 0, OpenGL_GetWidth(), OpenGL_GetHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
// render to the real buffer now
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Show the finished picture // Show the finished picture
@ -1003,15 +886,39 @@ void Renderer::Swap(const TRectangle& rc)
for (int i = 1; i < 8; ++i) for (int i = 1; i < 8; ++i)
TextureMngr::DisableStage(i); TextureMngr::DisableStage(i);
TRectangle back_rc;
ComputeBackbufferRectangle(&back_rc);
// Update GLViewPort
glViewport(
back_rc.left,
back_rc.top,
back_rc.right - back_rc.left,
back_rc.bottom - back_rc.top
);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// Place the texture // Copy the framebuffer to screen.
// TODO: Use glBlitFramebufferEXT.
float u_max;
float v_min = 0.f;
float v_max;
if (g_Config.bAutoScale) {
u_max = (rc.right - rc.left);
v_min = (float)GetTargetHeight() - (rc.bottom - rc.top);
v_max = (float)GetTargetHeight();
} else {
u_max = (float)GetTargetWidth();
v_max = (float)GetTargetHeight(); // TODO - when we change the target height to 528, this will have to change.
}
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2f(-1,-1); glTexCoord2f(0, v_min); glVertex2f(-1, -1);
glTexCoord2f(0, (float)GetTargetHeight()); glVertex2f(-1,1); glTexCoord2f(0, v_max); glVertex2f(-1, 1);
glTexCoord2f((float)GetTargetWidth(), (float)GetTargetHeight()); glVertex2f(1,1); glTexCoord2f(u_max, v_max); glVertex2f( 1, 1);
glTexCoord2f((float)GetTargetWidth(), 0); glVertex2f(1,-1); glTexCoord2f(u_max, v_min); glVertex2f( 1, -1);
glEnd(); glEnd();
// Wireframe // Wireframe
@ -1022,68 +929,16 @@ void Renderer::Swap(const TRectangle& rc)
TextureMngr::DisableStage(0); TextureMngr::DisableStage(0);
// ------------------------------------- // -------------------------------------
// Take screenshot, if requested
// ----------------------------------------------------------------------- if (s_bScreenshot) {
/* Blacken out the borders in the 4:3 or 16:9 aspect ratio modes. Somewhere in BPStructs 0x52 or
elsewhere the area outside the actual picture, that we now show with the aspect ratio option
has been filled with either for example white, or have copies of old renderings on it. So we
replace that with blacknes.
We are not supposed to need this with the Crop option and in full screen, but we can keep it for the
window mode, since the border can still be seen then
*/
// --------------------
if(g_Config.bKeepAR43 || g_Config.bKeepAR169)
{
// Set current drawing color to black
glColor3f(0.0, 0.0, 0.0);
/* This doesn't work
glRecti, glRectf(
(float)Left,
(float)Right,
(float)Top,
(float)Bottom); */
/* The glVertex3f() coordinates are:
Top: 1 to -1 from top to bottom
Left: 1 to -1 from right to left
Height and width is therefore 2.0, zero is the center of the screen
*/
// The fraction of the screen that the image occupies
/* It's hard to make a border that always exactly begin where the screen ends. The ( -1) here will
sometimes hide one pixel to many, but if we use (- 0) we will on the other hand sometimes show
one line of pixels that we should not show. But a -0.5 adjustment seemed just right, it never hid
one pixel to much, and never one to little. So I settle with a -0.5 adjustment here. */
float HeightRatio = (((float)(rc.bottom)) - 0.5) / 480.0f;
// Bottom border
float FLeft = 1.0,
FWidth = -2.0,
FHeight = 2.0 * (1.0 - HeightRatio),
FTop = -1.0 + FHeight;
glBegin(GL_POLYGON);
glVertex3f (FLeft, FTop - FHeight, 0.0);
glVertex3f (FLeft + FWidth, FTop - FHeight, 0.0);
glVertex3f (FLeft + FWidth, FTop, 0.0);
glVertex3f (FLeft, FTop, 0.0);
glEnd();
//Console::Print("Border Left:%1.3f Top:%1.3f Width:%1.3f Height:%1.3f\n", FLeft, FTop, FWidth, FHeight);
}
// -------------------------------------
// Take screenshot, if necessary
if(s_bScreenshot) {
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
if (SaveRenderTarget(s_sScreenshotName.c_str(), OpenGL_GetBackbufferWidth(), OpenGL_GetBackbufferHeight())) {
if(SaveRenderTarget(s_sScreenshotName.c_str())) {
char msg[255]; char msg[255];
sprintf(msg, "Saved %s\n", s_sScreenshotName.c_str()); sprintf(msg, "Saved %s\n", s_sScreenshotName.c_str());
OSD::AddMessage(msg, 2000); OSD::AddMessage(msg, 2000);
} else } else {
PanicAlert("Error while capturing screen"); PanicAlert("Error capturing or saving screenshot.");
}
s_sScreenshotName = ""; s_sScreenshotName = "";
s_bScreenshot = false; s_bScreenshot = false;
s_criticalScreenshot.Leave(); s_criticalScreenshot.Leave();
@ -1093,42 +948,23 @@ void Renderer::Swap(const TRectangle& rc)
SwapBuffers(); SwapBuffers();
RestoreGLState(); RestoreGLState();
#endif
GL_REPORT_ERRORD();
GL_REPORT_ERRORD();
g_Config.iSaveTargetId = 0; g_Config.iSaveTargetId = 0;
// For testing zbuffer targets.
// for testing zbuffer targets // Renderer::SetZBufferRender();
//Renderer::SetZBufferRender(); // SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight());
//SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_ARB, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight());
} }
//////////////////////////////////////////////// ////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////// void Renderer::DrawDebugText()
// We can now draw whatever we want on top of the picture. Then we copy the final picture to the output.
// ----------------------
void Renderer::SwapBuffers()
{ {
// ----------------------------------------------------------------------- // Draw various messages on the screen, like FPS, statistics, etc.
/* Draw messages on the screen */
// --------------------
static int fpscount;
static int s_fps;
static unsigned long lasttime;
char debugtext_buffer[8192]; char debugtext_buffer[8192];
char *p = debugtext_buffer; char *p = debugtext_buffer;
p[0] = 0; p[0] = 0;
++fpscount;
if (timeGetTime() - lasttime > 1000)
{
lasttime = timeGetTime();
s_fps = fpscount;
fpscount = 0;
}
if (g_Config.bShowFPS) if (g_Config.bShowFPS)
{ {
p+=sprintf(p, "FPS: %d\n", s_fps); p+=sprintf(p, "FPS: %d\n", s_fps);
@ -1162,6 +998,7 @@ void Renderer::SwapBuffers()
std::string text1; std::string text1;
VertexLoaderManager::AppendListToString(&text1); VertexLoaderManager::AppendListToString(&text1);
// TODO: Check for buffer overflow
p+=sprintf(p,"%s",text1.c_str()); p+=sprintf(p,"%s",text1.c_str());
} }
@ -1175,7 +1012,6 @@ void Renderer::SwapBuffers()
p+=sprintf(p,"Alpha Update: %s\n", stats.alphaUpdate==1 ? "Enabled" : "Disabled"); p+=sprintf(p,"Alpha Update: %s\n", stats.alphaUpdate==1 ? "Enabled" : "Disabled");
p+=sprintf(p,"Dst Alpha Enabled: %s\n", stats.dstAlphaEnable==1 ? "Enabled" : "Disabled"); p+=sprintf(p,"Dst Alpha Enabled: %s\n", stats.dstAlphaEnable==1 ? "Enabled" : "Disabled");
p+=sprintf(p,"Dst Alpha: %08x\n", stats.dstAlpha); p+=sprintf(p,"Dst Alpha: %08x\n", stats.dstAlpha);
} }
if (g_Config.bOverlayProjStats) if (g_Config.bOverlayProjStats)
@ -1202,11 +1038,29 @@ void Renderer::SwapBuffers()
// Render a shadow, and then the text. // Render a shadow, and then the text.
Renderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000); Renderer::RenderText(debugtext_buffer, 21, 21, 0xDD000000);
Renderer::RenderText(debugtext_buffer, 20, 20, 0xFF00FFFF); Renderer::RenderText(debugtext_buffer, 20, 20, 0xFF00FFFF);
}
//////////////////////////////////////////////////////////////////////////////////////
// We can now draw whatever we want on top of the picture. Then we copy the final picture to the output.
// ----------------------
void Renderer::SwapBuffers()
{
// Count FPS.
static int fpscount = 0;
static unsigned long lasttime;
++fpscount;
if (timeGetTime() - lasttime > 1000)
{
lasttime = timeGetTime();
s_fps = fpscount;
fpscount = 0;
}
DrawDebugText();
OSD::DrawMessages(); OSD::DrawMessages();
// ----------------------------- // -----------------------------
#if defined(DVPROFILE) #if defined(DVPROFILE)
if (g_bWriteProfile) { if (g_bWriteProfile) {
//g_bWriteProfile = 0; //g_bWriteProfile = 0;
@ -1219,17 +1073,17 @@ void Renderer::SwapBuffers()
} }
} }
#endif #endif
// Copy the rendered frame to the real window // Copy the rendered frame to the real window
OpenGL_SwapBuffers(); OpenGL_SwapBuffers();
glClearColor(0,0,0,0); glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// Clean out old stuff from caches // Clean out old stuff from caches
PixelShaderCache::Cleanup(); VertexShaderCache::ProgressiveCleanup();
PixelShaderCache::ProgressiveCleanup();
TextureMngr::ProgressiveCleanup(); TextureMngr::ProgressiveCleanup();
frameCount++; frameCount++;
@ -1239,7 +1093,6 @@ void Renderer::SwapBuffers()
// Render to the framebuffer. // Render to the framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, s_uFramebuffer);
if (nZBufferRender > 0) { if (nZBufferRender > 0) {
if (--nZBufferRender == 0) { if (--nZBufferRender == 0) {
// turn off // turn off
@ -1253,8 +1106,8 @@ void Renderer::SwapBuffers()
void Renderer::RenderText(const char* pstr, int left, int top, u32 color) void Renderer::RenderText(const char* pstr, int left, int top, u32 color)
{ {
int nBackbufferWidth = (int)OpenGL_GetWidth(); int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
int nBackbufferHeight = (int)OpenGL_GetHeight(); int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f, glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f); ((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
s_pfont->printMultilineText(pstr, s_pfont->printMultilineText(pstr,
@ -1268,51 +1121,35 @@ void Renderer::SetScreenshot(const char *filename)
s_criticalScreenshot.Enter(); s_criticalScreenshot.Enter();
s_sScreenshotName = filename; s_sScreenshotName = filename;
s_bScreenshot = true; s_bScreenshot = true;
s_criticalScreenshot.Leave(); s_criticalScreenshot.Leave();
} }
bool Renderer::SaveRenderTarget(const char *filename) bool Renderer::SaveRenderTarget(const char *filename, int w, int h)
{ {
int w = (int)OpenGL_GetWidth(), h = (int)OpenGL_GetHeight();
bool result = false;
if(!filename)
return false;
u8 *data = (u8 *)malloc(3 * w * h); u8 *data = (u8 *)malloc(3 * w * h);
glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data); glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, data);
if (glGetError() != GL_NO_ERROR) if (glGetError() != GL_NO_ERROR)
return false; return false;
// Flip image upside down. Damn OpenGL.
// Flip image for (int y = 0; y < h / 2; y++)
for(int y = 0; y < h / 2; y++) { {
for(int x = 0; x < w; x++) { for(int x = 0; x < w; x++)
std::swap(data[(y * w + x) * 3], {
data[((h - 1 - y) * w + x) * 3]); std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]);
std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]);
std::swap(data[(y * w + x) * 3 + 1], std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]);
data[((h - 1 - y) * w + x) * 3 + 1]);
std::swap(data[(y * w + x) * 3 + 2],
data[((h - 1 - y) * w + x) * 3 + 2]);
} }
} }
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
wxImage a(w, h, data); wxImage a(w, h, data);
a.SaveFile(wxString::FromAscii(filename), wxBITMAP_TYPE_BMP); a.SaveFile(wxString::FromAscii(filename), wxBITMAP_TYPE_BMP);
result = true; bool result = true;
#else #else
result = SaveTGA(filename, w, h, data); bool result = SaveTGA(filename, w, h, data);
free(data); free(data);
#endif #endif
return result; return result;
} }
@ -1339,60 +1176,29 @@ void UpdateViewport()
(rawViewport[5] - rawViewport[2]) / 16777215.0f, rawViewport[5] / 16777215.0f);*/ (rawViewport[5] - rawViewport[2]) / 16777215.0f, rawViewport[5] / 16777215.0f);*/
// -------------------------- // --------------------------
// -----------------------------------------------------------------------
// GLViewPort variables
// ------------------
int GLWidth, GLHeight, GLx, GLy;
float FloatGLWidth = fabs(2 * xfregs.rawViewport[0]);
float FloatGLHeight = fabs(2 * xfregs.rawViewport[1]);
// rawViewport[0] = 320, rawViewport[1] = -240
int scissorXOff = bpmem.scissorOffset.x * 2 - 342; int scissorXOff = bpmem.scissorOffset.x * 2 - 342;
int scissorYOff = bpmem.scissorOffset.y * 2 - 342; int scissorYOff = bpmem.scissorOffset.y * 2 - 342;
// ------------------------------------- // -------------------------------------
float MValueX = Renderer::GetTargetScaleX();
// ----------------------------------------------------------------------- float MValueY = Renderer::GetTargetScaleY();
// Stretch picture while keeping the native resolution
// ------------------
if (g_Config.bStretchToFit)
{
GLx = (int)(xfregs.rawViewport[3] - xfregs.rawViewport[0] - 342 - scissorXOff);
GLy = Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4] - xfregs.rawViewport[1] - 342 - scissorYOff));
// Round up to the nearest integer
GLWidth = (int)ceil(FloatGLWidth);
GLHeight = (int)ceil(FloatGLHeight);
}
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Stretch picture with increased internal resolution // Stretch picture with increased internal resolution
// ------------------ // ------------------
else int GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - 342 - scissorXOff) * MValueX);
{ int GLy = (int)ceil(Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4] - xfregs.rawViewport[1] - 342 - scissorYOff)) * MValueY);
float MValueX = OpenGL_GetXmax(); int GLWidth = (int)ceil(abs((int)(2 * xfregs.rawViewport[0])) * MValueX);
float MValueY = OpenGL_GetYmax(); int GLHeight = (int)ceil(abs((int)(2 * xfregs.rawViewport[1])) * MValueY);
GLx = (int)ceil((xfregs.rawViewport[3] - xfregs.rawViewport[0] - 342 - scissorXOff) * MValueX);
GLy = (int)ceil(Renderer::GetTargetHeight() - ((int)(xfregs.rawViewport[4] - xfregs.rawViewport[1] - 342 - scissorYOff)) * MValueY);
GLWidth = (int)ceil(abs((int)(2 * xfregs.rawViewport[0])) * MValueX);
GLHeight = (int)ceil(abs((int)(2 * xfregs.rawViewport[1])) * MValueY);
}
// ------------------------------------- // -------------------------------------
// Update the view port // Update the view port
glViewport( glViewport(GLx, GLy, GLWidth, GLHeight);
GLx, GLy,
GLWidth, GLHeight
);
// GLDepthRange - this could be a source of trouble - see the viewport hacks.
// -----------------------------------------------------------------------
// GLDepthRange
// ------------------
double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777215.0f; double GLNear = (xfregs.rawViewport[5] - xfregs.rawViewport[2]) / 16777215.0f;
double GLFar = xfregs.rawViewport[5] / 16777215.0f; double GLFar = xfregs.rawViewport[5] / 16777215.0f;
glDepthRange(GLNear, GLFar); glDepthRange(GLNear, GLFar);
// ------------------------------------- // -------------------------------------
// Logging // Logging

View File

@ -116,6 +116,10 @@ public:
static int GetTargetWidth(); static int GetTargetWidth();
static int GetTargetHeight(); static int GetTargetHeight();
// Multiply any 0-640 / 0-480 coordinates by these when rendering.
static float GetTargetScaleX();
static float GetTargetScaleY();
static void SetFramebuffer(GLuint fb); static void SetFramebuffer(GLuint fb);
static void SetZBufferRender(); // sets rendering of the zbuffer using MRTs static void SetZBufferRender(); // sets rendering of the zbuffer using MRTs
static void SetRenderTarget(GLuint targ); // if targ is 0, sets to original render target static void SetRenderTarget(GLuint targ); // if targ is 0, sets to original render target
@ -126,11 +130,14 @@ public:
// Random utilities // Random utilities
static void RenderText(const char* pstr, int left, int top, u32 color); static void RenderText(const char* pstr, int left, int top, u32 color);
static void DrawDebugText();
static void SetScreenshot(const char *filename); static void SetScreenshot(const char *filename);
static bool SaveRenderTarget(const char *filename); static bool SaveRenderTarget(const char *filename, int w, int h);
// Finish up the current frame, print some stats // Finish up the current frame, print some stats
static void Swap(const TRectangle& rc); static void Swap(const TRectangle& rc);
}; };
void ComputeBackbufferRectangle(TRectangle *rc);
#endif #endif

View File

@ -177,7 +177,7 @@ void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc,
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, srcTexture);
if(linearFilter) if (linearFilter)
{ {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -198,6 +198,7 @@ void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc,
glEnable(GL_FRAGMENT_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader.glprogid); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader.glprogid);
// Draw...
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1); glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1); glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1);
@ -206,6 +207,7 @@ void EncodeToRam(GLuint srcTexture, const TRectangle& sourceRc,
glEnd(); glEnd();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// .. and then readback the results.
// TODO: make this less slow. // TODO: make this less slow.
glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr); glReadPixels(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight, GL_BGRA, GL_UNSIGNED_BYTE, destAddr);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
@ -245,7 +247,7 @@ void EncodeToRam(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyf
u8* ptr = Memory_GetPtr(address); u8* ptr = Memory_GetPtr(address);
u32 target = bFromZBuffer?Renderer::GetZBufferTarget():Renderer::GetRenderTarget(); u32 target = bFromZBuffer ? Renderer::GetZBufferTarget() : Renderer::GetRenderTarget();
s32 width = source.right - source.left; s32 width = source.right - source.left;
s32 height = source.bottom - source.top; s32 height = source.bottom - source.top;

View File

@ -660,12 +660,12 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glBegin(GL_QUADS); glBegin(GL_QUADS);
float MValueX = OpenGL_GetXmax(); float MValueX = Renderer::GetTargetScaleX();
float MValueY = OpenGL_GetYmax(); float MValueY = Renderer::GetTargetScaleY();
glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(-1,1); glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(-1, 1);
glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(-1,-1); glTexCoord2f((float)source->left * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(-1, -1);
glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f(1,-1); glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->top * MValueY); glVertex2f( 1, -1);
glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f(1,1); glTexCoord2f((float)source->right * MValueX, Renderer::GetTargetHeight()-(float)source->bottom * MValueY); glVertex2f( 1, 1);
glEnd(); glEnd();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();

View File

@ -299,7 +299,7 @@ void Flush()
if (g_Config.iLog & CONF_SAVETARGETS) { if (g_Config.iLog & CONF_SAVETARGETS) {
char str[128]; char str[128];
sprintf(str, "%sframes/targ%.3d.tga", FULL_DUMP_DIR, g_Config.iSaveTargetId); sprintf(str, "%sframes/targ%.3d.tga", FULL_DUMP_DIR, g_Config.iSaveTargetId);
Renderer::SaveRenderTarget(str); Renderer::SaveRenderTarget(str, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
} }
#endif #endif
g_Config.iSaveTargetId++; g_Config.iSaveTargetId++;

View File

@ -109,7 +109,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
return pShaderLast; return pShaderLast;
} }
void VertexShaderCache::Cleanup() void VertexShaderCache::ProgressiveCleanup()
{ {
VSCache::iterator iter = vshaders.begin(); VSCache::iterator iter = vshaders.begin();
while (iter != vshaders.end()) { while (iter != vshaders.end()) {
@ -142,18 +142,15 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
return false; return false;
} }
//ERROR_LOG(VIDEO, pstrprogram); // This looks evil - we modify the program through the const char * we got from cgGetProgramString!
//ERROR_LOG(VIDEO, "id: %d\n", g_Config.iSaveTargetId); // It SHOULD not have any nasty side effects though - but you never know...
char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM);
char* pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); char *plocal = strstr(pcompiledprog, "program.local");
char* plocal = strstr(pcompiledprog, "program.local");
while (plocal != NULL) { while (plocal != NULL) {
const char* penv = " program.env"; const char* penv = " program.env";
memcpy(plocal, penv, 13); memcpy(plocal, penv, 13);
plocal = strstr(plocal+13, "program.local"); plocal = strstr(plocal + 13, "program.local");
} }
glGenProgramsARB(1, &vs.glprogid); glGenProgramsARB(1, &vs.glprogid);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid); glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vs.glprogid);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog);
@ -166,7 +163,6 @@ bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrpr
} }
cgDestroyProgram(tempprog); cgDestroyProgram(tempprog);
// printf("Compiled vertex shader %i\n", vs.glprogid);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
vs.strprog = pstrprogram; vs.strprog = pstrprogram;

View File

@ -51,7 +51,7 @@ class VertexShaderCache
public: public:
static void Init(); static void Init();
static void Cleanup(); static void ProgressiveCleanup();
static void Shutdown(); static void Shutdown();
static VERTEXSHADER* GetShader(u32 components); static VERTEXSHADER* GetShader(u32 components);

View File

@ -59,7 +59,6 @@ static struct
void XFB_SetUpdateArgs(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset); void XFB_SetUpdateArgs(u8* _pXFB, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset);
void XFB_Init() void XFB_Init()
{ {
glGenTextures(1, &xfb_decoded_texture); glGenTextures(1, &xfb_decoded_texture);
@ -81,23 +80,22 @@ int XFB_isInit()
void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt) void XFB_Write(u8 *xfb_in_ram, const TRectangle& sourceRc, u32 dstWd, u32 dstHt)
{ {
u32 nBackbufferHeight = OpenGL_GetHeight();
TRectangle renderSrcRc; TRectangle renderSrcRc;
renderSrcRc.left = sourceRc.left; renderSrcRc.left = sourceRc.left;
renderSrcRc.right = sourceRc.right; renderSrcRc.right = sourceRc.right;
renderSrcRc.top = nBackbufferHeight - sourceRc.top; // OpenGL upside down as usual...
renderSrcRc.bottom = nBackbufferHeight - sourceRc.bottom; renderSrcRc.top = Renderer::GetTargetHeight() - sourceRc.top;
renderSrcRc.bottom = Renderer::GetTargetHeight() - sourceRc.bottom;
TextureConverter::EncodeToRamYUYV(Renderer::GetRenderTarget(), renderSrcRc, xfb_in_ram, dstWd, dstHt); TextureConverter::EncodeToRamYUYV(Renderer::GetRenderTarget(), renderSrcRc, xfb_in_ram, dstWd, dstHt);
} }
// Draw the XFB straight to the OpenGL backbuffer.
void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset) void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset)
{ {
TextureConverter::DecodeToTexture(xfb_in_ram, width, height, xfb_decoded_texture); TextureConverter::DecodeToTexture(xfb_in_ram, width, height, xfb_decoded_texture);
OpenGL_Update(); // just updates the render window position and the backbuffer size OpenGL_Update(); // just updates the render window position and the backbuffer size
Renderer::ResetGLState(); Renderer::ResetGLState();
TextureMngr::EnableTexRECT(0); TextureMngr::EnableTexRECT(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the backbuffer
@ -105,8 +103,10 @@ void XFB_Draw(u8 *xfb_in_ram, u32 width, u32 height, s32 yOffset)
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfb_decoded_texture);
glViewport(OpenGL_GetXoff(), OpenGL_GetYoff(), TRectangle back_rc;
(int)OpenGL_GetWidth(), (int)OpenGL_GetHeight()); ComputeBackbufferRectangle(&back_rc);
glViewport(back_rc.left, back_rc.top, back_rc.right - back_rc.left, back_rc.bottom - back_rc.top);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
float w = (float)width; float w = (float)width;

View File

@ -138,12 +138,11 @@ RasterFont::RasterFont()
{ {
// set GL modes // set GL modes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font // create the raster font
fontOffset = glGenLists (128); fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++) { for (int i = 32; i < 127; i++) {
glNewList(i+fontOffset, GL_COMPILE); glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i-32]); glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
glEndList(); glEndList();
} }
} }
@ -167,60 +166,52 @@ void RasterFont::printString(const char *s, double x, double y, double z)
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z) void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
{ {
int length = (int)strlen(s); int length = (int)strlen(s);
int x = int(screen_width/2.0 - (length/2.0)*char_width); int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
printString(s, x, y, z); printString(s, x, y, z);
} }
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight) void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
{ {
double x=start_x; double x = start_x;
double y=start_y; double y = start_y;
static char temp[1024]; static char temp[1024];
char* t = temp; char *t = temp;
while (*text)
while(*text)
{ {
if(*text=='\n') if (*text == '\n')
{ {
*t=0; *t = 0;
printString(temp,x,y,z); printString(temp, x, y, z);
y-=char_height * 2.0f / bbHeight; y -= char_height * 2.0f / bbHeight;
x=start_x; x = start_x;
t=temp; t = temp;
} }
else if(*text=='\r') else if (*text == '\r')
{ {
t=temp; t = temp;
} }
else if(*text=='\t') else if (*text == '\t')
{ {
//todo: add tabs every something like 4*char_width //todo: add tabs every something like 4*char_width
*t=0; *t = 0;
int cpos = (int)strlen(temp); int cpos = (int)strlen(temp);
int newpos = (cpos + 4) & (~3);
int newpos = (cpos+4)&(~3); printString(temp, x, y, z);
x = start_x + (char_width*newpos) * 2.0f / bbWidth;
t = temp;
printString(temp,x,y,z); *t++ = ' ';
x =start_x + (char_width*newpos) * 2.0f / bbWidth;
t=temp;
*(t++)=' ';
} }
else else
{ {
*(t++)=*text; *t++ = *text;
} }
text++; text++;
} }
if(t!=text)
// ????
if (t != text)
{ {
*t=0; *t = 0;
printString(temp,x,y,z); printString(temp, x, y, z);
} }
} }

View File

@ -100,9 +100,9 @@ void GetMousePos(float& x, float& y)
// Calculate the new X offset // Calculate the new X offset
// ---------------- // ----------------
// Move the left of the picture to the middle of the screen // Move the left of the picture to the middle of the screen
XOffset = XOffset + WinWidth / 2.0; XOffset = XOffset + WinWidth / 2.0f;
// Then remove half the picture height to move it to the horizontal center // Then remove half the picture height to move it to the horizontal center
XOffset = XOffset - PictureWidth / 2.0; XOffset = XOffset - PictureWidth / 2.0f;
// -------------------- // --------------------
} }
// The window is to high, we have to limit the height // The window is to high, we have to limit the height
@ -112,7 +112,7 @@ void GetMousePos(float& x, float& y)
// Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen // Calculate the new width and height for glViewport, this is not the actual size of either the picture or the screen
// ---------------- // ----------------
// Invert the ratio to make it > 1 // Invert the ratio to make it > 1
Ratio = 1.0 / Ratio; Ratio = 1.0f / Ratio;
PictureHeight = WinHeight / Ratio; PictureHeight = WinHeight / Ratio;
// -------------------- // --------------------
@ -120,9 +120,9 @@ void GetMousePos(float& x, float& y)
// Calculate the new Y offset // Calculate the new Y offset
// ---------------- // ----------------
// Move the top of the picture to the middle of the screen // Move the top of the picture to the middle of the screen
YOffset = YOffset + WinHeight / 2.0; YOffset = YOffset + WinHeight / 2.0f;
// Then remove half the picture height to move it to the vertical center // Then remove half the picture height to move it to the vertical center
YOffset = YOffset - PictureHeight / 2.0; YOffset = YOffset - PictureHeight / 2.0f;
// -------------------- // --------------------
} }
// Logging // Logging
@ -141,11 +141,11 @@ void GetMousePos(float& x, float& y)
// ------------------ // ------------------
if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bCrop) if ((g_Config.bKeepAR43 || g_Config.bKeepAR169) && g_Config.bCrop)
{ {
float Ratio = g_Config.bKeepAR43 ? ((4.0 / 3.0) / (5.0 / 4.0)) : (((16.0 / 9.0) / (16.0 / 10.0))); float Ratio = g_Config.bKeepAR43 ? ((4.0f / 3.0f) / (5.0f / 4.0f)) : (((16.0f / 9.0f) / (16.0f / 10.0f)));
// The width and height we will add (calculate this before PictureWidth and PictureHeight is adjusted) // The width and height we will add (calculate this before PictureWidth and PictureHeight is adjusted)
float IncreasedWidth = (Ratio - 1.0) * PictureWidth; float IncreasedWidth = (Ratio - 1.0f) * PictureWidth;
float IncreasedHeight = (Ratio - 1.0) * PictureHeight; float IncreasedHeight = (Ratio - 1.0f) * PictureHeight;
// The new width and height // The new width and height
PictureWidth = PictureWidth * Ratio; PictureWidth = PictureWidth * Ratio;