mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-30 01:29:42 -06:00
Merge branch 'master' into perfqueries.
Conflicts: Source/Core/VideoCommon/Src/VideoConfig.h Source/Core/VideoCommon/VideoCommon.vcxproj.filters Source/Plugins/Plugin_VideoDX11/Src/VertexManager.cpp Source/Plugins/Plugin_VideoSoftware/Src/Rasterizer.cpp Source/Plugins/Plugin_VideoSoftware/Src/Tev.cpp
This commit is contained in:
@ -18,7 +18,6 @@
|
||||
#include "Globals.h"
|
||||
#include "VideoConfig.h"
|
||||
#include "IniFile.h"
|
||||
#include "Setup.h"
|
||||
#include "Core.h"
|
||||
#include "Host.h"
|
||||
#include "VideoBackend.h"
|
||||
@ -29,59 +28,8 @@
|
||||
|
||||
#include "GLUtil.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "EmuWindow.h"
|
||||
static HDC hDC = NULL; // Private GDI Device Context
|
||||
static HGLRC hRC = NULL; // Permanent Rendering Context
|
||||
#else
|
||||
GLWindow GLWin;
|
||||
#endif
|
||||
|
||||
// Handles OpenGL and the window
|
||||
|
||||
// Window dimensions.
|
||||
static int s_backbuffer_width;
|
||||
static int s_backbuffer_height;
|
||||
|
||||
void OpenGL_SwapBuffers()
|
||||
{
|
||||
#if defined(USE_WX) && USE_WX
|
||||
GLWin.glCanvas->SwapBuffers();
|
||||
#elif defined(__APPLE__)
|
||||
[GLWin.cocoaCtx flushBuffer];
|
||||
#elif defined(_WIN32)
|
||||
SwapBuffers(hDC);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
glXSwapBuffers(GLWin.dpy, GLWin.win);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 OpenGL_GetBackbufferWidth()
|
||||
{
|
||||
return s_backbuffer_width;
|
||||
}
|
||||
|
||||
u32 OpenGL_GetBackbufferHeight()
|
||||
{
|
||||
return s_backbuffer_height;
|
||||
}
|
||||
|
||||
void OpenGL_SetWindowText(const char *text)
|
||||
{
|
||||
#if defined(USE_WX) && USE_WX
|
||||
// Handled by Host_UpdateTitle()
|
||||
#elif defined(__APPLE__)
|
||||
[GLWin.cocoaWin setTitle: [NSString stringWithUTF8String: text]];
|
||||
#elif defined(_WIN32)
|
||||
TCHAR temp[512];
|
||||
swprintf_s(temp, sizeof(temp)/sizeof(TCHAR), _T("%hs"), text);
|
||||
EmuWindow::SetWindowText(temp);
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
// Tell X to ask the window manager to set the window title.
|
||||
// (X itself doesn't provide window title functionality.)
|
||||
XStoreName(GLWin.dpy, GLWin.win, text);
|
||||
#endif
|
||||
}
|
||||
cInterfaceBase *GLInterface;
|
||||
|
||||
namespace OGL
|
||||
{
|
||||
@ -89,20 +37,7 @@ namespace OGL
|
||||
// Draw messages on top of the screen
|
||||
unsigned int VideoBackend::PeekMessages()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// TODO: peekmessage
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return GLInterface->PeekMessages();
|
||||
}
|
||||
|
||||
// Show the current FPS
|
||||
@ -110,538 +45,105 @@ void VideoBackend::UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[100];
|
||||
snprintf(temp, sizeof temp, "%s | OpenGL | %s", scm_rev_str, text);
|
||||
OpenGL_SetWindowText(temp);
|
||||
return GLInterface->UpdateFPSDisplay(temp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(HAVE_X11) && HAVE_X11
|
||||
void XEventThread();
|
||||
|
||||
void CreateXWindow(void)
|
||||
void InitInterface()
|
||||
{
|
||||
Atom wmProtocols[1];
|
||||
|
||||
// Setup window attributes
|
||||
GLWin.attr.colormap = XCreateColormap(GLWin.evdpy,
|
||||
GLWin.parent, GLWin.vi->visual, AllocNone);
|
||||
GLWin.attr.event_mask = KeyPressMask | StructureNotifyMask | FocusChangeMask;
|
||||
GLWin.attr.background_pixel = BlackPixel(GLWin.evdpy, GLWin.screen);
|
||||
GLWin.attr.border_pixel = 0;
|
||||
|
||||
// Create the window
|
||||
GLWin.win = XCreateWindow(GLWin.evdpy, GLWin.parent,
|
||||
GLWin.x, GLWin.y, GLWin.width, GLWin.height, 0,
|
||||
GLWin.vi->depth, InputOutput, GLWin.vi->visual,
|
||||
CWBorderPixel | CWBackPixel | CWColormap | CWEventMask, &GLWin.attr);
|
||||
wmProtocols[0] = XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", True);
|
||||
XSetWMProtocols(GLWin.evdpy, GLWin.win, wmProtocols, 1);
|
||||
XSetStandardProperties(GLWin.evdpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL);
|
||||
XMapRaised(GLWin.evdpy, GLWin.win);
|
||||
XSync(GLWin.evdpy, True);
|
||||
|
||||
GLWin.xEventThread = std::thread(XEventThread);
|
||||
#ifdef ANDROID
|
||||
GLInterface = new cInterfaceBase;
|
||||
#elif defined(USE_EGL) && USE_EGL
|
||||
GLInterface = new cInterfaceEGL;
|
||||
#elif defined(USE_WX) && USE_WX
|
||||
GLInterface = new cInterfaceWX;
|
||||
#elif defined(__APPLE__)
|
||||
GLInterface = new cInterfaceAGL;
|
||||
#elif defined(_WIN32)
|
||||
GLInterface = new cInterfaceWGL;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
GLInterface = new cInterfaceGLX;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DestroyXWindow(void)
|
||||
GLuint OpenGL_CompileProgram ( const char* vertexShader, const char* fragmentShader )
|
||||
{
|
||||
XUnmapWindow(GLWin.dpy, GLWin.win);
|
||||
GLWin.win = 0;
|
||||
if (GLWin.xEventThread.joinable())
|
||||
GLWin.xEventThread.join();
|
||||
XFreeColormap(GLWin.evdpy, GLWin.attr.colormap);
|
||||
}
|
||||
|
||||
void XEventThread()
|
||||
{
|
||||
// Free look variables
|
||||
static bool mouseLookEnabled = false;
|
||||
static bool mouseMoveEnabled = false;
|
||||
static float lastMouse[2];
|
||||
while (GLWin.win)
|
||||
{
|
||||
XEvent event;
|
||||
KeySym key;
|
||||
for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--)
|
||||
{
|
||||
XNextEvent(GLWin.evdpy, &event);
|
||||
switch(event.type) {
|
||||
case KeyPress:
|
||||
key = XLookupKeysym((XKeyEvent*)&event, 0);
|
||||
switch (key)
|
||||
{
|
||||
case XK_3:
|
||||
OSDChoice = 1;
|
||||
// Toggle native resolution
|
||||
g_Config.iEFBScale = g_Config.iEFBScale + 1;
|
||||
if (g_Config.iEFBScale > 7) g_Config.iEFBScale = 0;
|
||||
break;
|
||||
case XK_4:
|
||||
OSDChoice = 2;
|
||||
// Toggle aspect ratio
|
||||
g_Config.iAspectRatio = (g_Config.iAspectRatio + 1) & 3;
|
||||
break;
|
||||
case XK_5:
|
||||
OSDChoice = 3;
|
||||
// Toggle EFB copy
|
||||
if (!g_Config.bEFBCopyEnable || g_Config.bCopyEFBToTexture)
|
||||
{
|
||||
g_Config.bEFBCopyEnable ^= true;
|
||||
g_Config.bCopyEFBToTexture = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_Config.bCopyEFBToTexture = !g_Config.bCopyEFBToTexture;
|
||||
}
|
||||
break;
|
||||
case XK_6:
|
||||
OSDChoice = 4;
|
||||
g_Config.bDisableFog = !g_Config.bDisableFog;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (g_Config.bFreeLook)
|
||||
{
|
||||
static float debugSpeed = 1.0f;
|
||||
switch (key)
|
||||
{
|
||||
case XK_parenleft:
|
||||
debugSpeed /= 2.0f;
|
||||
break;
|
||||
case XK_parenright:
|
||||
debugSpeed *= 2.0f;
|
||||
break;
|
||||
case XK_w:
|
||||
VertexShaderManager::TranslateView(0.0f, debugSpeed);
|
||||
break;
|
||||
case XK_s:
|
||||
VertexShaderManager::TranslateView(0.0f, -debugSpeed);
|
||||
break;
|
||||
case XK_a:
|
||||
VertexShaderManager::TranslateView(debugSpeed, 0.0f);
|
||||
break;
|
||||
case XK_d:
|
||||
VertexShaderManager::TranslateView(-debugSpeed, 0.0f);
|
||||
break;
|
||||
case XK_r:
|
||||
VertexShaderManager::ResetView();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonPress:
|
||||
if (g_Config.bFreeLook)
|
||||
{
|
||||
switch (event.xbutton.button)
|
||||
{
|
||||
case 2: // Middle button
|
||||
lastMouse[0] = event.xbutton.x;
|
||||
lastMouse[1] = event.xbutton.y;
|
||||
mouseMoveEnabled = true;
|
||||
break;
|
||||
case 3: // Right button
|
||||
lastMouse[0] = event.xbutton.x;
|
||||
lastMouse[1] = event.xbutton.y;
|
||||
mouseLookEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (g_Config.bFreeLook)
|
||||
{
|
||||
switch (event.xbutton.button)
|
||||
{
|
||||
case 2: // Middle button
|
||||
mouseMoveEnabled = false;
|
||||
break;
|
||||
case 3: // Right button
|
||||
mouseLookEnabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionNotify:
|
||||
if (g_Config.bFreeLook)
|
||||
{
|
||||
if (mouseLookEnabled)
|
||||
{
|
||||
VertexShaderManager::RotateView((event.xmotion.x - lastMouse[0]) / 200.0f,
|
||||
(event.xmotion.y - lastMouse[1]) / 200.0f);
|
||||
lastMouse[0] = event.xmotion.x;
|
||||
lastMouse[1] = event.xmotion.y;
|
||||
}
|
||||
|
||||
if (mouseMoveEnabled)
|
||||
{
|
||||
VertexShaderManager::TranslateView((event.xmotion.x - lastMouse[0]) / 50.0f,
|
||||
(event.xmotion.y - lastMouse[1]) / 50.0f);
|
||||
lastMouse[0] = event.xmotion.x;
|
||||
lastMouse[1] = event.xmotion.y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
Window winDummy;
|
||||
unsigned int borderDummy, depthDummy;
|
||||
XGetGeometry(GLWin.evdpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y,
|
||||
&GLWin.width, &GLWin.height, &borderDummy, &depthDummy);
|
||||
s_backbuffer_width = GLWin.width;
|
||||
s_backbuffer_height = GLWin.height;
|
||||
break;
|
||||
case ClientMessage:
|
||||
if ((unsigned long) event.xclient.data.l[0] ==
|
||||
XInternAtom(GLWin.evdpy, "WM_DELETE_WINDOW", False))
|
||||
Host_Message(WM_USER_STOP);
|
||||
if ((unsigned long) event.xclient.data.l[0] ==
|
||||
XInternAtom(GLWin.evdpy, "RESIZE", False))
|
||||
XMoveResizeWindow(GLWin.evdpy, GLWin.win,
|
||||
event.xclient.data.l[1], event.xclient.data.l[2],
|
||||
event.xclient.data.l[3], event.xclient.data.l[4]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Common::SleepCurrentThread(20);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create rendering window.
|
||||
// Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
|
||||
bool OpenGL_Create(void *&window_handle)
|
||||
{
|
||||
int _tx, _ty, _twidth, _theight;
|
||||
Host_GetRenderWindowSize(_tx, _ty, _twidth, _theight);
|
||||
|
||||
// Control window size and picture scaling
|
||||
s_backbuffer_width = _twidth;
|
||||
s_backbuffer_height = _theight;
|
||||
|
||||
#if defined(USE_WX) && USE_WX
|
||||
GLWin.panel = (wxPanel *)window_handle;
|
||||
GLWin.glCanvas = new wxGLCanvas(GLWin.panel, wxID_ANY, NULL,
|
||||
wxPoint(0, 0), wxSize(_twidth, _theight));
|
||||
GLWin.glCanvas->Show(true);
|
||||
if (GLWin.glCtxt == NULL) // XXX dirty hack
|
||||
GLWin.glCtxt = new wxGLContext(GLWin.glCanvas);
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
NSRect size;
|
||||
NSUInteger style = NSMiniaturizableWindowMask;
|
||||
NSOpenGLPixelFormatAttribute attr[2] = { NSOpenGLPFADoubleBuffer, 0 };
|
||||
NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc]
|
||||
initWithAttributes: attr];
|
||||
if (fmt == nil) {
|
||||
ERROR_LOG(VIDEO, "failed to create pixel format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GLWin.cocoaCtx = [[NSOpenGLContext alloc]
|
||||
initWithFormat: fmt shareContext: nil];
|
||||
[fmt release];
|
||||
if (GLWin.cocoaCtx == nil) {
|
||||
ERROR_LOG(VIDEO, "failed to create context");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) {
|
||||
size = [[NSScreen mainScreen] frame];
|
||||
style |= NSBorderlessWindowMask;
|
||||
} else {
|
||||
size = NSMakeRect(_tx, _ty, _twidth, _theight);
|
||||
style |= NSResizableWindowMask | NSTitledWindowMask;
|
||||
}
|
||||
|
||||
GLWin.cocoaWin = [[NSWindow alloc] initWithContentRect: size
|
||||
styleMask: style backing: NSBackingStoreBuffered defer: NO];
|
||||
if (GLWin.cocoaWin == nil) {
|
||||
ERROR_LOG(VIDEO, "failed to create window");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bFullscreen) {
|
||||
CGDisplayCapture(CGMainDisplayID());
|
||||
[GLWin.cocoaWin setLevel: CGShieldingWindowLevel()];
|
||||
}
|
||||
|
||||
[GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
|
||||
[GLWin.cocoaWin makeKeyAndOrderFront: nil];
|
||||
|
||||
#elif defined(_WIN32)
|
||||
window_handle = (void*)EmuWindow::Create((HWND)window_handle, GetModuleHandle(0), _T("Please wait..."));
|
||||
if (window_handle == NULL)
|
||||
{
|
||||
Host_SysMessage("failed to create window");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Show the window
|
||||
EmuWindow::Show();
|
||||
|
||||
PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
|
||||
{
|
||||
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
|
||||
1, // Version Number
|
||||
PFD_DRAW_TO_WINDOW | // Format Must Support Window
|
||||
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
|
||||
PFD_DOUBLEBUFFER, // Must Support Double Buffering
|
||||
PFD_TYPE_RGBA, // Request An RGBA Format
|
||||
32, // Select Our Color Depth
|
||||
0, 0, 0, 0, 0, 0, // Color Bits Ignored
|
||||
0, // 8bit Alpha Buffer
|
||||
0, // Shift Bit Ignored
|
||||
0, // No Accumulation Buffer
|
||||
0, 0, 0, 0, // Accumulation Bits Ignored
|
||||
24, // 24Bit Z-Buffer (Depth Buffer)
|
||||
8, // 8bit Stencil Buffer
|
||||
0, // No Auxiliary Buffer
|
||||
PFD_MAIN_PLANE, // Main Drawing Layer
|
||||
0, // Reserved
|
||||
0, 0, 0 // Layer Masks Ignored
|
||||
};
|
||||
|
||||
GLuint PixelFormat; // Holds The Results After Searching For A Match
|
||||
|
||||
if (!(hDC=GetDC(EmuWindow::GetWnd()))) {
|
||||
PanicAlert("(1) Can't create an OpenGL Device context. Fail.");
|
||||
return false;
|
||||
}
|
||||
if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {
|
||||
PanicAlert("(2) Can't find a suitable PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {
|
||||
PanicAlert("(3) Can't set the PixelFormat.");
|
||||
return false;
|
||||
}
|
||||
if (!(hRC = wglCreateContext(hDC))) {
|
||||
PanicAlert("(4) Can't create an OpenGL rendering context.");
|
||||
return false;
|
||||
}
|
||||
// --------------------------------------
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
int glxMajorVersion, glxMinorVersion;
|
||||
|
||||
// attributes for a single buffered visual in RGBA format with at least
|
||||
// 8 bits per color and a 24 bit depth buffer
|
||||
int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
None};
|
||||
|
||||
// attributes for a double buffered visual in RGBA format with at least
|
||||
// 8 bits per color and a 24 bit depth buffer
|
||||
int attrListDbl[] = {GLX_RGBA, GLX_DOUBLEBUFFER,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_SAMPLE_BUFFERS_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
|
||||
GLX_SAMPLES_ARB, g_Config.iMultisampleMode != MULTISAMPLE_OFF?1:0,
|
||||
None };
|
||||
|
||||
int attrListDefault[] = {
|
||||
GLX_RGBA,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_DEPTH_SIZE, 1,
|
||||
None };
|
||||
|
||||
GLWin.dpy = XOpenDisplay(0);
|
||||
GLWin.evdpy = XOpenDisplay(0);
|
||||
GLWin.parent = (Window)window_handle;
|
||||
GLWin.screen = DefaultScreen(GLWin.dpy);
|
||||
if (GLWin.parent == 0)
|
||||
GLWin.parent = RootWindow(GLWin.dpy, GLWin.screen);
|
||||
|
||||
glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion);
|
||||
NOTICE_LOG(VIDEO, "glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
|
||||
|
||||
// Get an appropriate visual
|
||||
GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
|
||||
if (GLWin.vi == NULL)
|
||||
{
|
||||
GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl);
|
||||
if (GLWin.vi != NULL)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Only single buffered visual!");
|
||||
}
|
||||
else
|
||||
{
|
||||
GLWin.vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDefault);
|
||||
if (GLWin.vi == NULL)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Could not choose visual (glXChooseVisual)");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
NOTICE_LOG(VIDEO, "Got double buffered visual!");
|
||||
|
||||
// Create a GLX context.
|
||||
GLWin.ctx = glXCreateContext(GLWin.dpy, GLWin.vi, 0, GL_TRUE);
|
||||
if (!GLWin.ctx)
|
||||
{
|
||||
PanicAlert("Unable to create GLX context.");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLWin.x = _tx;
|
||||
GLWin.y = _ty;
|
||||
GLWin.width = _twidth;
|
||||
GLWin.height = _theight;
|
||||
|
||||
CreateXWindow();
|
||||
window_handle = (void *)GLWin.win;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpenGL_MakeCurrent()
|
||||
{
|
||||
// connect the glx-context to the window
|
||||
#if defined(USE_WX) && USE_WX
|
||||
return GLWin.glCanvas->SetCurrent(*GLWin.glCtxt);
|
||||
#elif defined(__APPLE__)
|
||||
[GLWin.cocoaCtx makeCurrentContext];
|
||||
#elif defined(_WIN32)
|
||||
return wglMakeCurrent(hDC, hRC) ? true : false;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
#if defined(HAVE_WX) && (HAVE_WX)
|
||||
Host_GetRenderWindowSize(GLWin.x, GLWin.y,
|
||||
(int&)GLWin.width, (int&)GLWin.height);
|
||||
XMoveResizeWindow(GLWin.dpy, GLWin.win, GLWin.x, GLWin.y,
|
||||
GLWin.width, GLWin.height);
|
||||
#endif
|
||||
return glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update window width, size and etc. Called from Render.cpp
|
||||
void OpenGL_Update()
|
||||
{
|
||||
#if defined(USE_WX) && USE_WX
|
||||
int width, height;
|
||||
|
||||
GLWin.panel->GetSize(&width, &height);
|
||||
if (width == s_backbuffer_width && height == s_backbuffer_height)
|
||||
return;
|
||||
|
||||
GLWin.glCanvas->SetFocus();
|
||||
GLWin.glCanvas->SetSize(0, 0, width, height);
|
||||
GLWin.glCtxt->SetCurrent(*GLWin.glCanvas);
|
||||
s_backbuffer_width = width;
|
||||
s_backbuffer_height = height;
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
int width, height;
|
||||
|
||||
width = [[GLWin.cocoaWin contentView] frame].size.width;
|
||||
height = [[GLWin.cocoaWin contentView] frame].size.height;
|
||||
if (width == s_backbuffer_width && height == s_backbuffer_height)
|
||||
return;
|
||||
|
||||
[GLWin.cocoaCtx setView: [GLWin.cocoaWin contentView]];
|
||||
[GLWin.cocoaCtx update];
|
||||
[GLWin.cocoaCtx makeCurrentContext];
|
||||
s_backbuffer_width = width;
|
||||
s_backbuffer_height = height;
|
||||
|
||||
#elif defined(_WIN32)
|
||||
RECT rcWindow;
|
||||
if (!EmuWindow::GetParentWnd())
|
||||
{
|
||||
// We are not rendering to a child window - use client size.
|
||||
GetClientRect(EmuWindow::GetWnd(), &rcWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We are rendering to a child window - use parent size.
|
||||
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
|
||||
}
|
||||
|
||||
// Get the new window width and height
|
||||
// See below for documentation
|
||||
int width = rcWindow.right - rcWindow.left;
|
||||
int height = rcWindow.bottom - rcWindow.top;
|
||||
|
||||
// If we are rendering to a child window
|
||||
if (EmuWindow::GetParentWnd() != 0 &&
|
||||
(s_backbuffer_width != width || s_backbuffer_height != height) &&
|
||||
width >= 4 && height >= 4)
|
||||
{
|
||||
::MoveWindow(EmuWindow::GetWnd(), 0, 0, width, height, FALSE);
|
||||
s_backbuffer_width = width;
|
||||
s_backbuffer_height = height;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close backend
|
||||
void OpenGL_Shutdown()
|
||||
{
|
||||
#if defined(USE_WX) && USE_WX
|
||||
GLWin.glCanvas->Hide();
|
||||
// XXX GLWin.glCanvas->Destroy();
|
||||
// XXX delete GLWin.glCtxt;
|
||||
#elif defined(__APPLE__)
|
||||
[GLWin.cocoaWin close];
|
||||
[GLWin.cocoaCtx clearDrawable];
|
||||
[GLWin.cocoaCtx release];
|
||||
#elif defined(_WIN32)
|
||||
if (hRC)
|
||||
{
|
||||
if (!wglMakeCurrent(NULL, NULL))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
|
||||
if (!wglDeleteContext(hRC))
|
||||
ERROR_LOG(VIDEO, "Release Rendering Context Failed.");
|
||||
|
||||
hRC = NULL;
|
||||
}
|
||||
|
||||
if (hDC && !ReleaseDC(EmuWindow::GetWnd(), hDC))
|
||||
{
|
||||
ERROR_LOG(VIDEO, "Release Device Context Failed.");
|
||||
hDC = NULL;
|
||||
}
|
||||
// generate objects
|
||||
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
GLuint programID = glCreateProgram();
|
||||
GLint Result = GL_FALSE;
|
||||
char stringBuffer[1024];
|
||||
GLsizei stringBufferUsage = 0;
|
||||
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
DestroyXWindow();
|
||||
if (GLWin.ctx && !glXMakeCurrent(GLWin.dpy, None, NULL))
|
||||
NOTICE_LOG(VIDEO, "Could not release drawing context.");
|
||||
if (GLWin.ctx)
|
||||
{
|
||||
glXDestroyContext(GLWin.dpy, GLWin.ctx);
|
||||
XCloseDisplay(GLWin.dpy);
|
||||
XCloseDisplay(GLWin.evdpy);
|
||||
GLWin.ctx = NULL;
|
||||
// compile vertex shader
|
||||
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
|
||||
glCompileShader(vertexShaderID);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
||||
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderInfoLog(vertexShaderID, 1024, &stringBufferUsage, stringBuffer);
|
||||
if(Result && stringBufferUsage) {
|
||||
ERROR_LOG(VIDEO, "GLSL vertex shader warnings:\n%s%s", stringBuffer, vertexShader);
|
||||
} else if(!Result) {
|
||||
ERROR_LOG(VIDEO, "GLSL vertex shader error:\n%s%s", stringBuffer, vertexShader);
|
||||
} else {
|
||||
DEBUG_LOG(VIDEO, "GLSL vertex shader compiled:\n%s", vertexShader);
|
||||
}
|
||||
bool shader_errors = !Result;
|
||||
#endif
|
||||
|
||||
// compile fragment shader
|
||||
glShaderSource(fragmentShaderID, 1, &fragmentShader, NULL);
|
||||
glCompileShader(fragmentShaderID);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
||||
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &Result);
|
||||
glGetShaderInfoLog(fragmentShaderID, 1024, &stringBufferUsage, stringBuffer);
|
||||
if(Result && stringBufferUsage) {
|
||||
ERROR_LOG(VIDEO, "GLSL fragment shader warnings:\n%s%s", stringBuffer, fragmentShader);
|
||||
} else if(!Result) {
|
||||
ERROR_LOG(VIDEO, "GLSL fragment shader error:\n%s%s", stringBuffer, fragmentShader);
|
||||
} else {
|
||||
DEBUG_LOG(VIDEO, "GLSL fragment shader compiled:\n%s", fragmentShader);
|
||||
}
|
||||
shader_errors |= !Result;
|
||||
#endif
|
||||
|
||||
// link them
|
||||
glAttachShader(programID, vertexShaderID);
|
||||
glAttachShader(programID, fragmentShaderID);
|
||||
glLinkProgram(programID);
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(DEBUG_GLSL)
|
||||
glGetProgramiv(programID, GL_LINK_STATUS, &Result);
|
||||
glGetProgramInfoLog(programID, 1024, &stringBufferUsage, stringBuffer);
|
||||
if(Result && stringBufferUsage) {
|
||||
ERROR_LOG(VIDEO, "GLSL linker warnings:\n%s%s%s", stringBuffer, vertexShader, fragmentShader);
|
||||
} else if(!Result && !shader_errors) {
|
||||
ERROR_LOG(VIDEO, "GLSL linker error:\n%s%s%s", stringBuffer, vertexShader, fragmentShader);
|
||||
}
|
||||
#endif
|
||||
|
||||
// cleanup
|
||||
glDeleteShader(vertexShaderID);
|
||||
glDeleteShader(fragmentShaderID);
|
||||
|
||||
return programID;
|
||||
}
|
||||
|
||||
|
||||
GLuint OpenGL_ReportGLError(const char *function, const char *file, int line)
|
||||
{
|
||||
GLint err = glGetError();
|
||||
if (err != GL_NO_ERROR)
|
||||
{
|
||||
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL error 0x%x - %s\n",
|
||||
file, line, function, err, gluErrorString(err));
|
||||
ERROR_LOG(VIDEO, "%s:%d: (%s) OpenGL error 0x%x\n",
|
||||
file, line, function, err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void OpenGL_ReportARBProgramError()
|
||||
{
|
||||
#ifndef USE_GLES
|
||||
const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
|
||||
if (pstr != NULL && pstr[0] != 0)
|
||||
{
|
||||
@ -651,10 +153,12 @@ void OpenGL_ReportARBProgramError()
|
||||
ERROR_LOG(VIDEO, "%s", (char*)pstr);
|
||||
ERROR_LOG(VIDEO, "\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
|
||||
{
|
||||
#ifndef USE_GLES
|
||||
unsigned int fbo_status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
if (fbo_status != GL_FRAMEBUFFER_COMPLETE_EXT)
|
||||
{
|
||||
@ -687,6 +191,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
|
||||
file, line, function, error);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -20,26 +20,7 @@
|
||||
|
||||
#include "VideoConfig.h"
|
||||
#include "MathUtil.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GLEW_STATIC
|
||||
#include <GL/glew.h>
|
||||
#include <GL/wglew.h>
|
||||
#elif defined HAVE_X11 && HAVE_X11
|
||||
#include <GL/glxew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#elif defined __APPLE__
|
||||
#include <GL/glew.h>
|
||||
#import <AppKit/AppKit.h>
|
||||
#endif
|
||||
|
||||
#if defined USE_WX && USE_WX
|
||||
#include "wx/wx.h"
|
||||
#include "wx/glcanvas.h"
|
||||
#endif
|
||||
#include "GLInterface.h"
|
||||
|
||||
#ifndef GL_DEPTH24_STENCIL8_EXT // allows FBOs to support stencils
|
||||
#define GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
@ -48,53 +29,28 @@
|
||||
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLES
|
||||
#define TEX2D GL_TEXTURE_2D
|
||||
#define PREC "highp"
|
||||
#define TEXTYPE "sampler2D"
|
||||
#define TEXFUNC "texture2D"
|
||||
#else
|
||||
#define TEX2D GL_TEXTURE_RECTANGLE_ARB
|
||||
#define PREC
|
||||
#define TEXTYPE "sampler2DRect"
|
||||
#define TEXFUNC "texture2DRect"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct {
|
||||
#if defined(USE_WX) && USE_WX
|
||||
wxGLCanvas *glCanvas;
|
||||
wxGLContext *glCtxt;
|
||||
wxPanel *panel;
|
||||
#elif defined(__APPLE__)
|
||||
NSWindow *cocoaWin;
|
||||
NSOpenGLContext *cocoaCtx;
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
int screen;
|
||||
Window win;
|
||||
Window parent;
|
||||
// dpy used for glx stuff, evdpy for window events etc.
|
||||
// evdpy is to be used by XEventThread only
|
||||
Display *dpy, *evdpy;
|
||||
XVisualInfo *vi;
|
||||
GLXContext ctx;
|
||||
XSetWindowAttributes attr;
|
||||
std::thread xEventThread;
|
||||
int x, y;
|
||||
unsigned int width, height;
|
||||
#endif
|
||||
} GLWindow;
|
||||
void InitInterface();
|
||||
|
||||
extern GLWindow GLWin;
|
||||
|
||||
#endif
|
||||
|
||||
// Public OpenGL util
|
||||
|
||||
// Initialization / upkeep
|
||||
bool OpenGL_Create(void *&);
|
||||
void OpenGL_Shutdown();
|
||||
void OpenGL_Update();
|
||||
bool OpenGL_MakeCurrent();
|
||||
void OpenGL_SwapBuffers();
|
||||
|
||||
// Get status
|
||||
u32 OpenGL_GetBackbufferWidth();
|
||||
u32 OpenGL_GetBackbufferHeight();
|
||||
|
||||
// Set things
|
||||
void OpenGL_SetWindowText(const char *text);
|
||||
// Helpers
|
||||
GLuint OpenGL_CompileProgram(const char *vertexShader, const char *fragmentShader);
|
||||
|
||||
// Error reporting - use the convenient macros.
|
||||
void OpenGL_ReportARBProgramError();
|
||||
@ -126,4 +82,7 @@ extern CGprofile g_cgvProf, g_cgfProf;
|
||||
// use GLSL shaders across the whole pipeline. Yikes!
|
||||
//#define USE_DUAL_SOURCE_BLEND
|
||||
|
||||
// TODO: should be removed if we use glsl a lot
|
||||
#define DEBUG_GLSL
|
||||
|
||||
#endif // _GLINIT_H_
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "GLUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
#include "MemoryUtil.h"
|
||||
#include "VertexShaderGen.h"
|
||||
|
||||
|
@ -61,6 +61,8 @@
|
||||
#include "Movie.h"
|
||||
#include "Host.h"
|
||||
#include "BPFunctions.h"
|
||||
#include "FPSCounter.h"
|
||||
#include "ConfigManager.h"
|
||||
|
||||
#include "main.h" // Local
|
||||
#ifdef _WIN32
|
||||
@ -130,58 +132,6 @@ const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_
|
||||
static bool s_efbCacheValid[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT];
|
||||
static std::vector<u32> s_efbCache[2][EFB_CACHE_WIDTH * EFB_CACHE_HEIGHT]; // 2 for PEEK_Z and PEEK_COLOR
|
||||
|
||||
static const GLenum glSrcFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_DST_COLOR,
|
||||
GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
GL_DST_ALPHA,
|
||||
GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
static const GLenum glDestFactors[8] = {
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_SRC_COLOR,
|
||||
GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
GL_DST_ALPHA,
|
||||
GL_ONE_MINUS_DST_ALPHA
|
||||
};
|
||||
|
||||
static const GLenum glCmpFuncs[8] = {
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS
|
||||
};
|
||||
|
||||
static const GLenum glLogicOpCodes[16] = {
|
||||
GL_CLEAR,
|
||||
GL_AND,
|
||||
GL_AND_REVERSE,
|
||||
GL_COPY,
|
||||
GL_AND_INVERTED,
|
||||
GL_NOOP,
|
||||
GL_XOR,
|
||||
GL_OR,
|
||||
GL_NOR,
|
||||
GL_EQUIV,
|
||||
GL_INVERT,
|
||||
GL_OR_REVERSE,
|
||||
GL_COPY_INVERTED,
|
||||
GL_OR_INVERTED,
|
||||
GL_NAND,
|
||||
GL_SET
|
||||
};
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
void HandleCgError(CGcontext ctx, CGerror err, void* appdata)
|
||||
@ -251,6 +201,8 @@ Renderer::Renderer()
|
||||
s_fps=0;
|
||||
s_blendMode = 0;
|
||||
|
||||
InitFPSCounter();
|
||||
|
||||
#if defined HAVE_CG && HAVE_CG
|
||||
g_cgcontext = cgCreateContext();
|
||||
cgGetError();
|
||||
@ -319,29 +271,12 @@ Renderer::Renderer()
|
||||
return; // TODO: fail
|
||||
|
||||
// Decide frambuffer size
|
||||
s_backbuffer_width = (int)OpenGL_GetBackbufferWidth();
|
||||
s_backbuffer_height = (int)OpenGL_GetBackbufferHeight();
|
||||
s_backbuffer_width = (int)GLInterface->GetBackBufferWidth();
|
||||
s_backbuffer_height = (int)GLInterface->GetBackBufferHeight();
|
||||
|
||||
// Handle VSync on/off
|
||||
#ifdef __APPLE__
|
||||
int swapInterval = g_ActiveConfig.bVSync ? 1 : 0;
|
||||
#if defined USE_WX && USE_WX
|
||||
NSOpenGLContext *ctx = GLWin.glCtxt->GetWXGLContext();
|
||||
#else
|
||||
NSOpenGLContext *ctx = GLWin.cocoaCtx;
|
||||
#endif
|
||||
[ctx setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval];
|
||||
#elif defined _WIN32
|
||||
if (WGLEW_EXT_swap_control)
|
||||
wglSwapIntervalEXT(g_ActiveConfig.bVSync ? 1 : 0);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
if (glXSwapIntervalSGI)
|
||||
glXSwapIntervalSGI(g_ActiveConfig.bVSync ? 1 : 0);
|
||||
else
|
||||
ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate).");
|
||||
#endif
|
||||
GLInterface->SwapInterval(swapInterval);
|
||||
|
||||
// check the max texture width and height
|
||||
GLint max_texture_size;
|
||||
@ -359,16 +294,14 @@ Renderer::Renderer()
|
||||
if (!GLEW_ARB_texture_non_power_of_two)
|
||||
WARN_LOG(VIDEO, "ARB_texture_non_power_of_two not supported.");
|
||||
|
||||
s_XFB_width = MAX_XFB_WIDTH;
|
||||
s_XFB_height = MAX_XFB_HEIGHT;
|
||||
// TODO: Move these somewhere else?
|
||||
FramebufferManagerBase::SetLastXfbWidth(MAX_XFB_WIDTH);
|
||||
FramebufferManagerBase::SetLastXfbHeight(MAX_XFB_HEIGHT);
|
||||
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
|
||||
CalculateXYScale(dst_rect);
|
||||
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
||||
|
||||
s_LastEFBScale = g_ActiveConfig.iEFBScale;
|
||||
CalculateTargetSize();
|
||||
CalculateTargetSize(s_backbuffer_width, s_backbuffer_height);
|
||||
|
||||
// Because of the fixed framebuffer size we need to disable the resolution
|
||||
// options while running
|
||||
@ -519,7 +452,7 @@ Renderer::~Renderer()
|
||||
void Renderer::DrawDebugInfo()
|
||||
{
|
||||
// Reset viewport for drawing text
|
||||
glViewport(0, 0, OpenGL_GetBackbufferWidth(), OpenGL_GetBackbufferHeight());
|
||||
glViewport(0, 0, GLInterface->GetBackBufferWidth(), GLInterface->GetBackBufferHeight());
|
||||
// Draw various messages on the screen, like FPS, statistics, etc.
|
||||
char debugtext_buffer[8192];
|
||||
char *p = debugtext_buffer;
|
||||
@ -528,6 +461,9 @@ void Renderer::DrawDebugInfo()
|
||||
if (g_ActiveConfig.bShowFPS)
|
||||
p+=sprintf(p, "FPS: %d\n", s_fps);
|
||||
|
||||
if (SConfig::GetInstance().m_ShowLag)
|
||||
p+=sprintf(p, "Lag: %llu\n", Movie::g_currentLagCount);
|
||||
|
||||
if (g_ActiveConfig.bShowInputDisplay)
|
||||
p+=sprintf(p, "%s", Movie::GetInputDisplay().c_str());
|
||||
|
||||
@ -593,18 +529,23 @@ void Renderer::DrawDebugInfo()
|
||||
|
||||
void Renderer::RenderText(const char *text, int left, int top, u32 color)
|
||||
{
|
||||
const int nBackbufferWidth = (int)OpenGL_GetBackbufferWidth();
|
||||
const int nBackbufferHeight = (int)OpenGL_GetBackbufferHeight();
|
||||
const int nBackbufferWidth = (int)GLInterface->GetBackBufferWidth();
|
||||
const int nBackbufferHeight = (int)GLInterface->GetBackBufferHeight();
|
||||
|
||||
glColor4f(((color>>16) & 0xff)/255.0f, ((color>> 8) & 0xff)/255.0f,
|
||||
((color>> 0) & 0xff)/255.0f, ((color>>24) & 0xFF)/255.0f);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
s_pfont->printMultilineText(text,
|
||||
left * 2.0f / (float)nBackbufferWidth - 1,
|
||||
1 - top * 2.0f / (float)nBackbufferHeight,
|
||||
0, nBackbufferWidth, nBackbufferHeight);
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
|
||||
@ -636,10 +577,13 @@ void Renderer::SetColorMask()
|
||||
{
|
||||
// Only enable alpha channel if it's supported by the current EFB format
|
||||
GLenum ColorMask = GL_FALSE, AlphaMask = GL_FALSE;
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
ColorMask = GL_TRUE;
|
||||
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
|
||||
AlphaMask = GL_TRUE;
|
||||
if (bpmem.alpha_test.TestResult() != AlphaTest::FAIL)
|
||||
{
|
||||
if (bpmem.blendmode.colorupdate)
|
||||
ColorMask = GL_TRUE;
|
||||
if (bpmem.blendmode.alphaupdate && (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24))
|
||||
AlphaMask = GL_TRUE;
|
||||
}
|
||||
glColorMask(ColorMask, ColorMask, ColorMask, AlphaMask);
|
||||
}
|
||||
|
||||
@ -912,6 +856,32 @@ void Renderer::ReinterpretPixelData(unsigned int convtype)
|
||||
|
||||
void Renderer::SetBlendMode(bool forceUpdate)
|
||||
{
|
||||
// Our render target always uses an alpha channel, so we need to override the blend functions to assume a destination alpha of 1 if the render target isn't supposed to have an alpha channel
|
||||
// Example: D3DBLEND_DESTALPHA needs to be D3DBLEND_ONE since the result without an alpha channel is assumed to always be 1.
|
||||
bool target_has_alpha = bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24;
|
||||
const GLenum glSrcFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_DST_COLOR,
|
||||
GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||
};
|
||||
const GLenum glDestFactors[8] =
|
||||
{
|
||||
GL_ZERO,
|
||||
GL_ONE,
|
||||
GL_SRC_COLOR,
|
||||
GL_ONE_MINUS_SRC_COLOR,
|
||||
GL_SRC_ALPHA,
|
||||
GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA
|
||||
(target_has_alpha) ? GL_DST_ALPHA : (GLenum)GL_ONE,
|
||||
(target_has_alpha) ? GL_ONE_MINUS_DST_ALPHA : (GLenum)GL_ZERO
|
||||
};
|
||||
|
||||
// blend mode bit mask
|
||||
// 0 - blend enable
|
||||
// 2 - reverse subtract enable (else add)
|
||||
@ -955,10 +925,10 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
|
||||
if (changes & 0x1F8)
|
||||
{
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
GLenum srcFactor = glSrcFactors[(newval >> 3) & 7];
|
||||
GLenum srcFactorAlpha = srcFactor;
|
||||
GLenum dstFactor = glDestFactors[(newval >> 6) & 7];
|
||||
#ifdef USE_DUAL_SOURCE_BLEND
|
||||
GLenum srcFactorAlpha = srcFactor;
|
||||
GLenum dstFactorAlpha = dstFactor;
|
||||
if (useDualSource)
|
||||
{
|
||||
@ -979,53 +949,53 @@ void Renderer::SetBlendMode(bool forceUpdate)
|
||||
// blend RGB change
|
||||
glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha);
|
||||
#else
|
||||
glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]);
|
||||
glBlendFunc(srcFactor, dstFactor);
|
||||
#endif
|
||||
}
|
||||
|
||||
s_blendMode = newval;
|
||||
}
|
||||
|
||||
void DumpFrame(const std::vector<u8>& data, int w, int h)
|
||||
{
|
||||
#if defined(HAVE_LIBAV) || defined(_WIN32)
|
||||
if (g_ActiveConfig.bDumpFrames && !data.empty())
|
||||
{
|
||||
AVIDump::AddFrame(&data[0], w, h);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This function has the final picture. We adjust the aspect ratio here.
|
||||
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,const EFBRectangle& rc,float Gamma)
|
||||
{
|
||||
static int w = 0, h = 0;
|
||||
if (g_bSkipCurrentFrame || (!XFBWrited && (!g_ActiveConfig.bUseXFB || !g_ActiveConfig.bUseRealXFB)) || !fbWidth || !fbHeight)
|
||||
if (g_bSkipCurrentFrame || (!XFBWrited && !g_ActiveConfig.RealXFBEnabled()) || !fbWidth || !fbHeight)
|
||||
{
|
||||
if (g_ActiveConfig.bDumpFrames && frame_data)
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#elif defined HAVE_LIBAV
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#endif
|
||||
DumpFrame(frame_data, w, h);
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
// this function is called after the XFB field is changed, not after
|
||||
// EFB is copied to XFB. In this way, flickering is reduced in games
|
||||
// and seems to also give more FPS in ZTP
|
||||
|
||||
if (field == FIELD_LOWER) xfbAddr -= fbWidth * 2;
|
||||
u32 xfbCount = 0;
|
||||
const XFBSourceBase* const* xfbSourceList = FramebufferManager::GetXFBSource(xfbAddr, fbWidth, fbHeight, xfbCount);
|
||||
if ((!xfbSourceList || xfbCount == 0) && g_ActiveConfig.bUseXFB && !g_ActiveConfig.bUseRealXFB)
|
||||
if (g_ActiveConfig.VirtualXFBEnabled() && (!xfbSourceList || xfbCount == 0))
|
||||
{
|
||||
if (g_ActiveConfig.bDumpFrames && frame_data)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#elif defined HAVE_LIBAV
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#endif
|
||||
}
|
||||
DumpFrame(frame_data, w, h);
|
||||
Core::Callback_VideoCopiedToXFB(false);
|
||||
return;
|
||||
}
|
||||
|
||||
ResetAPIState();
|
||||
|
||||
TargetRectangle dst_rect;
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, true, &dst_rect);
|
||||
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
||||
TargetRectangle flipped_trc = GetTargetRectangle();
|
||||
|
||||
// Flip top and bottom for some reason; TODO: Fix the code to suck less?
|
||||
int tmp = flipped_trc.top;
|
||||
flipped_trc.top = flipped_trc.bottom;
|
||||
flipped_trc.bottom = tmp;
|
||||
|
||||
// Textured triangles are necessary because of post-processing shaders
|
||||
|
||||
@ -1034,7 +1004,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
OGL::TextureCache::DisableStage(i);
|
||||
|
||||
// Update GLViewPort
|
||||
glViewport(dst_rect.left, dst_rect.bottom, dst_rect.GetWidth(), dst_rect.GetHeight());
|
||||
glViewport(flipped_trc.left, flipped_trc.bottom, flipped_trc.GetWidth(), flipped_trc.GetHeight());
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
@ -1065,7 +1035,14 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
MathUtil::Rectangle<float> drawRc;
|
||||
|
||||
if (!g_ActiveConfig.bUseRealXFB)
|
||||
if (g_ActiveConfig.bUseRealXFB)
|
||||
{
|
||||
drawRc.top = 1;
|
||||
drawRc.bottom = -1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// use virtual xfb with offset
|
||||
int xfbHeight = xfbSource->srcHeight;
|
||||
@ -1079,21 +1056,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
// The following code disables auto stretch. Kept for reference.
|
||||
// scale draw area for a 1 to 1 pixel mapping with the draw target
|
||||
//float vScale = (float)fbHeight / (float)dst_rect.GetHeight();
|
||||
//float hScale = (float)fbWidth / (float)dst_rect.GetWidth();
|
||||
//float vScale = (float)fbHeight / (float)flipped_trc.GetHeight();
|
||||
//float hScale = (float)fbWidth / (float)flipped_trc.GetWidth();
|
||||
//drawRc.top *= vScale;
|
||||
//drawRc.bottom *= vScale;
|
||||
//drawRc.left *= hScale;
|
||||
//drawRc.right *= hScale;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawRc.top = 1;
|
||||
drawRc.bottom = -1;
|
||||
drawRc.left = -1;
|
||||
drawRc.right = 1;
|
||||
}
|
||||
|
||||
// Tell the OSD Menu about the current internal resolution
|
||||
OSDInternalW = xfbSource->sourceRc.GetWidth(); OSDInternalH = xfbSource->sourceRc.GetHeight();
|
||||
|
||||
@ -1165,7 +1134,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
if (s_bScreenshot)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
|
||||
SaveScreenshot(s_sScreenshotName, dst_rect);
|
||||
SaveScreenshot(s_sScreenshotName, flipped_trc);
|
||||
// Reset settings
|
||||
s_sScreenshotName.clear();
|
||||
s_bScreenshot = false;
|
||||
@ -1176,16 +1145,15 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
if (g_ActiveConfig.bDumpFrames)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
|
||||
if (!frame_data || w != dst_rect.GetWidth() ||
|
||||
h != dst_rect.GetHeight())
|
||||
if (frame_data.empty() || w != flipped_trc.GetWidth() ||
|
||||
h != flipped_trc.GetHeight())
|
||||
{
|
||||
if (frame_data) delete[] frame_data;
|
||||
w = dst_rect.GetWidth();
|
||||
h = dst_rect.GetHeight();
|
||||
frame_data = new char[3 * w * h];
|
||||
w = flipped_trc.GetWidth();
|
||||
h = flipped_trc.GetHeight();
|
||||
frame_data.resize(3 * w * h);
|
||||
}
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
|
||||
glReadPixels(flipped_trc.left, flipped_trc.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
|
||||
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
|
||||
{
|
||||
if (!bLastFrameDumped)
|
||||
@ -1206,12 +1174,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
}
|
||||
if (bAVIDumping)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
AVIDump::AddFrame(frame_data);
|
||||
#else
|
||||
FlipImageData((u8*)frame_data, w, h);
|
||||
AVIDump::AddFrame((u8*)frame_data, w, h);
|
||||
#ifndef _WIN32
|
||||
FlipImageData(&frame_data[0], w, h);
|
||||
#endif
|
||||
|
||||
AVIDump::AddFrame(&frame_data[0], w, h);
|
||||
}
|
||||
|
||||
bLastFrameDumped = true;
|
||||
@ -1223,12 +1190,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
{
|
||||
if (bLastFrameDumped && bAVIDumping)
|
||||
{
|
||||
if (frame_data)
|
||||
{
|
||||
delete[] frame_data;
|
||||
frame_data = NULL;
|
||||
w = h = 0;
|
||||
}
|
||||
std::vector<u8>().swap(frame_data);
|
||||
w = h = 0;
|
||||
AVIDump::Stop();
|
||||
bAVIDumping = false;
|
||||
OSD::AddMessage("Stop dumping frames", 2000);
|
||||
@ -1240,11 +1203,11 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_criticalScreenshot);
|
||||
std::string movie_file_name;
|
||||
w = dst_rect.GetWidth();
|
||||
h = dst_rect.GetHeight();
|
||||
frame_data = new char[3 * w * h];
|
||||
w = GetTargetRectangle().GetWidth();
|
||||
h = GetTargetRectangle().GetHeight();
|
||||
frame_data.resize(3 * w * h);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
glReadPixels(dst_rect.left, dst_rect.bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, frame_data);
|
||||
glReadPixels(GetTargetRectangle().left, GetTargetRectangle().bottom, w, h, GL_BGR, GL_UNSIGNED_BYTE, &frame_data[0]);
|
||||
if (GL_REPORT_ERROR() == GL_NO_ERROR)
|
||||
{
|
||||
if (!bLastFrameDumped)
|
||||
@ -1255,21 +1218,17 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
OSD::AddMessage("Error opening framedump.raw for writing.", 2000);
|
||||
else
|
||||
{
|
||||
char msg [255];
|
||||
sprintf(msg, "Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h);
|
||||
OSD::AddMessage(msg, 2000);
|
||||
OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d RGB24)", movie_file_name.c_str(), w, h).c_str(), 2000);
|
||||
}
|
||||
}
|
||||
if (pFrameDump)
|
||||
{
|
||||
FlipImageData((u8*)frame_data, w, h);
|
||||
pFrameDump.WriteBytes(frame_data, w * 3 * h);
|
||||
FlipImageData(&frame_data[0], w, h);
|
||||
pFrameDump.WriteBytes(&frame_data[0], w * 3 * h);
|
||||
pFrameDump.Flush();
|
||||
}
|
||||
bLastFrameDumped = true;
|
||||
}
|
||||
|
||||
delete[] frame_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1283,24 +1242,22 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
SetWindowSize(fbWidth, fbHeight);
|
||||
|
||||
OpenGL_Update(); // just updates the render window position and the backbuffer size
|
||||
GLInterface->Update(); // just updates the render window position and the backbuffer size
|
||||
|
||||
bool xfbchanged = false;
|
||||
|
||||
if (s_XFB_width != fbWidth || s_XFB_height != fbHeight)
|
||||
if (FramebufferManagerBase::LastXfbWidth() != fbWidth || FramebufferManagerBase::LastXfbHeight() != fbHeight)
|
||||
{
|
||||
xfbchanged = true;
|
||||
s_XFB_width = fbWidth;
|
||||
s_XFB_height = fbHeight;
|
||||
if (s_XFB_width < 1) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_width > MAX_XFB_WIDTH) s_XFB_width = MAX_XFB_WIDTH;
|
||||
if (s_XFB_height < 1) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
if (s_XFB_height > MAX_XFB_HEIGHT) s_XFB_height = MAX_XFB_HEIGHT;
|
||||
unsigned int const last_w = (fbWidth < 1 || fbWidth > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbWidth;
|
||||
unsigned int const last_h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight;
|
||||
FramebufferManagerBase::SetLastXfbWidth(last_w);
|
||||
FramebufferManagerBase::SetLastXfbHeight(last_h);
|
||||
}
|
||||
|
||||
bool WindowResized = false;
|
||||
int W = (int)OpenGL_GetBackbufferWidth();
|
||||
int H = (int)OpenGL_GetBackbufferHeight();
|
||||
int W = (int)GLInterface->GetBackBufferWidth();
|
||||
int H = (int)GLInterface->GetBackBufferHeight();
|
||||
if (W != s_backbuffer_width || H != s_backbuffer_height || s_LastEFBScale != g_ActiveConfig.iEFBScale)
|
||||
{
|
||||
WindowResized = true;
|
||||
@ -1311,11 +1268,9 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
|
||||
if (xfbchanged || WindowResized || (s_LastMultisampleMode != g_ActiveConfig.iMultisampleMode))
|
||||
{
|
||||
ComputeDrawRectangle(s_backbuffer_width, s_backbuffer_height, false, &dst_rect);
|
||||
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
|
||||
|
||||
CalculateXYScale(dst_rect);
|
||||
|
||||
if (CalculateTargetSize() || (s_LastMultisampleMode != g_ActiveConfig.iMultisampleMode))
|
||||
if (CalculateTargetSize(s_backbuffer_width, s_backbuffer_height) || s_LastMultisampleMode != g_ActiveConfig.iMultisampleMode)
|
||||
{
|
||||
s_LastMultisampleMode = g_ActiveConfig.iMultisampleMode;
|
||||
s_MSAASamples = GetNumMSAASamples(s_LastMultisampleMode);
|
||||
@ -1328,20 +1283,8 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
}
|
||||
}
|
||||
|
||||
// Place messages on the picture, then copy it to the screen
|
||||
// ---------------------------------------------------------------------
|
||||
// Count FPS.
|
||||
// -------------
|
||||
static int fpscount = 0;
|
||||
static unsigned long lasttime = 0;
|
||||
if (Common::Timer::GetTimeMs() - lasttime >= 1000)
|
||||
{
|
||||
lasttime = Common::Timer::GetTimeMs();
|
||||
s_fps = fpscount;
|
||||
fpscount = 0;
|
||||
}
|
||||
if (XFBWrited)
|
||||
++fpscount;
|
||||
s_fps = UpdateFPSCounter();
|
||||
// ---------------------------------------------------------------------
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
@ -1359,7 +1302,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
// Copy the rendered frame to the real window
|
||||
OpenGL_SwapBuffers();
|
||||
GLInterface->Swap();
|
||||
|
||||
GL_REPORT_ERRORD();
|
||||
|
||||
@ -1455,6 +1398,18 @@ void Renderer::SetGenerationMode()
|
||||
|
||||
void Renderer::SetDepthMode()
|
||||
{
|
||||
const GLenum glCmpFuncs[8] =
|
||||
{
|
||||
GL_NEVER,
|
||||
GL_LESS,
|
||||
GL_EQUAL,
|
||||
GL_LEQUAL,
|
||||
GL_GREATER,
|
||||
GL_NOTEQUAL,
|
||||
GL_GEQUAL,
|
||||
GL_ALWAYS
|
||||
};
|
||||
|
||||
if (bpmem.zmode.testenable)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -1472,7 +1427,27 @@ void Renderer::SetDepthMode()
|
||||
|
||||
void Renderer::SetLogicOpMode()
|
||||
{
|
||||
if (bpmem.blendmode.logicopenable && bpmem.blendmode.logicmode != 3)
|
||||
const GLenum glLogicOpCodes[16] =
|
||||
{
|
||||
GL_CLEAR,
|
||||
GL_AND,
|
||||
GL_AND_REVERSE,
|
||||
GL_COPY,
|
||||
GL_AND_INVERTED,
|
||||
GL_NOOP,
|
||||
GL_XOR,
|
||||
GL_OR,
|
||||
GL_NOR,
|
||||
GL_EQUIV,
|
||||
GL_INVERT,
|
||||
GL_OR_REVERSE,
|
||||
GL_COPY_INVERTED,
|
||||
GL_OR_INVERTED,
|
||||
GL_NAND,
|
||||
GL_SET
|
||||
};
|
||||
|
||||
if (bpmem.blendmode.logicopenable)
|
||||
{
|
||||
glEnable(GL_COLOR_LOGIC_OP);
|
||||
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
||||
|
@ -58,24 +58,6 @@ namespace OGL
|
||||
|
||||
static u32 s_TempFramebuffer = 0;
|
||||
|
||||
static const GLint c_MinLinearFilter[8] = {
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
|
||||
static const GLint c_WrapSettings[4] = {
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level)
|
||||
{
|
||||
int width = std::max(virtual_width >> level, 1);
|
||||
@ -196,12 +178,14 @@ TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width,
|
||||
entry.pcfmt = pcfmt;
|
||||
|
||||
entry.bHaveMipMaps = tex_levels != 1;
|
||||
|
||||
entry.Load(width, height, expanded_width, 0);
|
||||
|
||||
return &entry;
|
||||
}
|
||||
|
||||
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips)
|
||||
unsigned int expanded_width, unsigned int level)
|
||||
{
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
@ -212,16 +196,7 @@ void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, expanded_width);
|
||||
|
||||
if (bHaveMipMaps && autogen_mips)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, level, gl_iformat, width, height, 0, gl_format, gl_type, temp);
|
||||
|
||||
if (expanded_width != width)
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
@ -330,15 +305,15 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
srcRect);
|
||||
|
||||
u8* dst = Memory::GetPointer(addr);
|
||||
u64 hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
u64 const new_hash = GetHash64(dst,encoded_size,g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
|
||||
// Mark texture entries in destination address range dynamic unless caching is enabled and the texture entry is up to date
|
||||
if (!g_ActiveConfig.bEFBCopyCacheEnable)
|
||||
TextureCache::MakeRangeDynamic(addr,encoded_size);
|
||||
else if (!TextureCache::Find(addr, hash))
|
||||
else if (!TextureCache::Find(addr, new_hash))
|
||||
TextureCache::MakeRangeDynamic(addr,encoded_size);
|
||||
|
||||
this->hash = hash;
|
||||
hash = new_hash;
|
||||
}
|
||||
|
||||
FramebufferManager::SetFramebuffer(0);
|
||||
@ -357,35 +332,43 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
|
||||
|
||||
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
|
||||
{
|
||||
// TODO: not used anywhere
|
||||
TexMode0 mode = newmode;
|
||||
//mode1 = newmode1;
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
if (bHaveMipMaps)
|
||||
const GLint c_MinLinearFilter[8] =
|
||||
{
|
||||
// TODO: not used anywhere
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
mode.min_filter += 4; // take equivalent forced linear
|
||||
GL_NEAREST,
|
||||
GL_NEAREST_MIPMAP_NEAREST,
|
||||
GL_NEAREST_MIPMAP_LINEAR,
|
||||
GL_NEAREST,
|
||||
GL_LINEAR,
|
||||
GL_LINEAR_MIPMAP_NEAREST,
|
||||
GL_LINEAR_MIPMAP_LINEAR,
|
||||
GL_LINEAR,
|
||||
};
|
||||
const GLint c_WrapSettings[4] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE,
|
||||
GL_REPEAT,
|
||||
GL_MIRRORED_REPEAT,
|
||||
GL_REPEAT,
|
||||
};
|
||||
|
||||
int filt = newmode.min_filter;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias / 32.0f));
|
||||
}
|
||||
else
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
|
||||
int filt = newmode.min_filter;
|
||||
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
|
||||
filt += 4; // take equivalent forced linear
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod / 16.f);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod / 16.f);
|
||||
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (s32)newmode.lod_bias / 32.0f);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
|
||||
|
||||
// TODO: Reset anisotrop when changed to 1
|
||||
if (g_Config.iMaxAnisotropy >= 1)
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
|
||||
}
|
||||
|
||||
TextureCache::~TextureCache()
|
||||
|
@ -54,7 +54,7 @@ private:
|
||||
~TCacheEntry();
|
||||
|
||||
void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips = false);
|
||||
unsigned int expanded_width, unsigned int level);
|
||||
|
||||
void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
|
@ -70,6 +70,16 @@ VertexManager::VertexManager()
|
||||
GL_REPORT_ERRORD();
|
||||
}
|
||||
|
||||
void VertexManager::CreateDeviceObjects()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
void VertexManager::DestroyDeviceObjects()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VertexManager::Draw()
|
||||
{
|
||||
if (IndexGenerator::GetNumTriangles() > 0)
|
||||
@ -119,8 +129,8 @@ void VertexManager::vFlush()
|
||||
xfregs.postMtxInfo[i].index, xfregs.postMtxInfo[i].normalize);
|
||||
}
|
||||
|
||||
PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphafunc=0x%x", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages,
|
||||
bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alphaFunc.hex>>16)&0xff);
|
||||
PRIM_LOG("pixel: tev=%d, ind=%d, texgen=%d, dstalpha=%d, alphatest=0x%x", bpmem.genMode.numtevstages+1, bpmem.genMode.numindstages,
|
||||
bpmem.genMode.numtexgens, (u32)bpmem.dstalpha.enable, (bpmem.alpha_test.hex>>16)&0xff);
|
||||
#endif
|
||||
|
||||
(void)GL_REPORT_ERROR();
|
||||
@ -155,8 +165,8 @@ void VertexManager::vFlush()
|
||||
tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1,
|
||||
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9,
|
||||
tex.texTlut[i&3].tlut_format,
|
||||
(tex.texMode0[i&3].min_filter & 3) && (tex.texMode0[i&3].min_filter != 8),
|
||||
tex.texMode1[i&3].max_lod >> 4,
|
||||
(tex.texMode0[i&3].min_filter & 3),
|
||||
(tex.texMode1[i&3].max_lod + 0xf) / 0x10,
|
||||
tex.texImage1[i&3].image_type);
|
||||
|
||||
if (tentry)
|
||||
|
@ -33,7 +33,8 @@ public:
|
||||
VertexManager();
|
||||
|
||||
NativeVertexFormat* CreateNativeVertexFormat();
|
||||
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
private:
|
||||
void Draw();
|
||||
// temp
|
||||
|
@ -88,7 +88,6 @@ Make AA apply instantly during gameplay if possible
|
||||
#include "TextureConverter.h"
|
||||
#include "PostProcessing.h"
|
||||
#include "OnScreenDisplay.h"
|
||||
#include "Setup.h"
|
||||
#include "DLCache.h"
|
||||
#include "FramebufferManager.h"
|
||||
#include "Core.h"
|
||||
@ -132,6 +131,7 @@ void InitBackendInfo()
|
||||
{
|
||||
g_Config.backend_info.APIType = API_OPENGL;
|
||||
g_Config.backend_info.bUseRGBATextures = false;
|
||||
g_Config.backend_info.bUseMinimalMipCount = false;
|
||||
g_Config.backend_info.bSupports3DVision = false;
|
||||
g_Config.backend_info.bSupportsDualSourceBlend = false; // supported, but broken
|
||||
g_Config.backend_info.bSupportsFormatReinterpretation = false;
|
||||
@ -168,7 +168,8 @@ bool VideoBackend::Initialize(void *&window_handle)
|
||||
g_Config.VerifyValidity();
|
||||
UpdateActiveConfig();
|
||||
|
||||
if (!OpenGL_Create(window_handle))
|
||||
InitInterface();
|
||||
if (!GLInterface->Create(window_handle))
|
||||
return false;
|
||||
|
||||
s_BackendInitialized = true;
|
||||
@ -180,7 +181,7 @@ bool VideoBackend::Initialize(void *&window_handle)
|
||||
// Run from the graphics thread
|
||||
void VideoBackend::Video_Prepare()
|
||||
{
|
||||
OpenGL_MakeCurrent();
|
||||
GLInterface->MakeCurrent();
|
||||
|
||||
g_renderer = new Renderer;
|
||||
|
||||
@ -206,7 +207,9 @@ void VideoBackend::Video_Prepare()
|
||||
GL_REPORT_ERRORD();
|
||||
VertexLoaderManager::Init();
|
||||
TextureConverter::Init();
|
||||
#ifndef _M_GENERIC
|
||||
DLCache::Init();
|
||||
#endif
|
||||
|
||||
// Notify the core that the video backend is ready
|
||||
Host_Message(WM_USER_CREATE);
|
||||
@ -221,7 +224,9 @@ void VideoBackend::Shutdown()
|
||||
s_efbAccessRequested = false;
|
||||
s_FifoShuttingDown = false;
|
||||
s_swapRequested = false;
|
||||
#ifndef _M_GENERIC
|
||||
DLCache::Shutdown();
|
||||
#endif
|
||||
Fifo_Shutdown();
|
||||
PostProcessing::Shutdown();
|
||||
|
||||
@ -240,7 +245,7 @@ void VideoBackend::Shutdown()
|
||||
g_renderer = NULL;
|
||||
g_texture_cache = NULL;
|
||||
}
|
||||
OpenGL_Shutdown();
|
||||
GLInterface->Shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user