Merge branch 'master' into GLSL-master

Conflicts:
	Source/Core/DolphinWX/Src/VideoConfigDiag.h
	Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h
	Source/Plugins/Plugin_VideoOGL/Src/Render.cpp
	Source/Plugins/Plugin_VideoOGL/Src/TextureCache.cpp
	Source/Plugins/Plugin_VideoOGL/Src/TextureConverter.cpp
This commit is contained in:
degasus
2012-12-27 10:36:54 +01:00
316 changed files with 27897 additions and 22577 deletions

View File

@ -13,11 +13,22 @@ set(SRCS Src/FramebufferManager.cpp
Src/VertexManager.cpp)
set(LIBS videocommon
GLEW
SOIL
common
${OPENGL_LIBRARIES}
${X11_LIBRARIES})
if(USE_EGL)
set(LIBS ${LIBS}
EGL)
endif()
if(USE_GLES)
set(LIBS ${LIBS}
GLESv2)
else()
set(LIBS ${LIBS}
GLEW
${OPENGL_LIBRARIES})
endif()
if(wxWidgets_FOUND)
set(LIBS ${LIBS} ${wxWidgets_LIBRARIES})

View File

@ -249,4 +249,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -17,6 +17,7 @@
#include "Globals.h"
#include "FramebufferManager.h"
#include "VertexShaderGen.h"
#include "TextureConverter.h"
#include "Render.h"
@ -27,6 +28,11 @@ namespace OGL
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp. ugly.
static GLuint s_VBO = 0;
static GLuint s_VAO = 0;
static MathUtil::Rectangle<float> s_cached_sourcerc;
static MathUtil::Rectangle<float> s_cached_drawrc;
int FramebufferManager::m_targetWidth;
int FramebufferManager::m_targetHeight;
int FramebufferManager::m_msaaSamples;
@ -53,6 +59,15 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
m_resolvedDepthTexture = 0;
m_xfbFramebuffer = 0;
s_cached_sourcerc.bottom = -1;
s_cached_sourcerc.left = -1;
s_cached_sourcerc.right = -1;
s_cached_sourcerc.top = -1;
s_cached_drawrc.bottom = -1;
s_cached_drawrc.left = -1;
s_cached_drawrc.right = -1;
s_cached_drawrc.top = -1;
m_targetWidth = targetWidth;
m_targetHeight = targetHeight;
@ -169,7 +184,28 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
// Generate VBO & VAO - and initialize the VAO for "Draw"
glGenBuffers(1, &s_VBO);
glGenVertexArrays(1, &s_VAO);
glBindBuffer(GL_ARRAY_BUFFER, s_VBO);
glBindVertexArray(s_VAO);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 6*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 6*sizeof(GLfloat), (GLfloat*)NULL+2);
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 6*sizeof(GLfloat), (GLfloat*)NULL+4);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f
glViewport(0, 0, m_targetWidth, m_targetHeight);
glScissor(0, 0, m_targetWidth, m_targetHeight);
@ -181,6 +217,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
FramebufferManager::~FramebufferManager()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteBuffers(1, &s_VBO);
glDeleteVertexArrays(1, &s_VAO);
GLuint glObj[3];
@ -305,24 +343,37 @@ void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture);
glBegin(GL_QUADS);
glTexCoord2f(sourcerc.left, sourcerc.bottom);
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
glVertex2f(drawrc.left, drawrc.bottom);
glTexCoord2f(sourcerc.left, sourcerc.top);
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
glVertex2f(drawrc.left, drawrc.top);
glTexCoord2f(sourcerc.right, sourcerc.top);
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
glVertex2f(drawrc.right, drawrc.top);
glTexCoord2f(sourcerc.right, sourcerc.bottom);
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
glVertex2f(drawrc.right, drawrc.bottom);
glEnd();
if(!(s_cached_sourcerc == sourcerc) || !(s_cached_drawrc == drawrc)) {
GLfloat vertices[] = {
drawrc.left, drawrc.bottom,
sourcerc.left, sourcerc.bottom,
0.0f, 0.0f,
drawrc.left, drawrc.top,
sourcerc.left, sourcerc.top,
0.0f, 1.0f,
drawrc.right, drawrc.top,
sourcerc.right, sourcerc.top,
1.0f, 1.0f,
drawrc.right, drawrc.bottom,
sourcerc.right, sourcerc.bottom,
1.0f, 0.0f
};
glBindBuffer(GL_ARRAY_BUFFER, s_VBO);
glBufferData(GL_ARRAY_BUFFER, 2*4*3*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
s_cached_sourcerc = sourcerc;
s_cached_drawrc = drawrc;
}
glBindVertexArray(s_VAO);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
GL_REPORT_ERRORD();
}

View File

@ -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,103 @@ 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);
#if 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 +151,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 +189,7 @@ bool OpenGL_ReportFBOError(const char *function, const char *file, int line)
file, line, function, error);
return false;
}
#endif
return true;
}

View File

@ -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();

View File

@ -28,8 +28,9 @@
#define COMPILED_CODE_SIZE 4096
// TODO: this guy is never initialized
u32 s_prevcomponents; // previous state set
// TODO: Use this again for performance, but without VAO we never know exactly the last configuration
static u32 s_prevcomponents; // previous state set
/*
#ifdef _WIN32
#ifdef _M_IX86
@ -65,7 +66,6 @@ public:
virtual void Initialize(const PortableVertexDeclaration &_vtx_decl);
virtual void SetupVertexPointers();
virtual void EnableComponents(u32 components);
};
namespace OGL
@ -188,6 +188,7 @@ void GLVertexFormat::SetupVertexPointers() {
#ifdef USE_JIT
((void (*)())(void*)m_compiledCode)();
#else
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
if (vtx_decl.num_normals >= 1) {
glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
@ -220,34 +221,32 @@ void GLVertexFormat::SetupVertexPointers() {
glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
}
#endif
}
void GLVertexFormat::EnableComponents(u32 components)
{
if (s_prevcomponents != components)
if (s_prevcomponents != m_components)
{
VertexManager::Flush();
// vertices
glEnableClientState(GL_VERTEX_ARRAY);
// matrices
if ((components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
if ((m_components & VB_HAS_POSMTXIDX) != (s_prevcomponents & VB_HAS_POSMTXIDX))
{
if (components & VB_HAS_POSMTXIDX)
if (m_components & VB_HAS_POSMTXIDX)
glEnableVertexAttribArray(SHADER_POSMTX_ATTRIB);
else
glDisableVertexAttribArray(SHADER_POSMTX_ATTRIB);
}
// normals
if ((components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
if ((m_components & VB_HAS_NRM0) != (s_prevcomponents & VB_HAS_NRM0))
{
if (components & VB_HAS_NRM0)
if (m_components & VB_HAS_NRM0)
glEnableClientState(GL_NORMAL_ARRAY);
else
glDisableClientState(GL_NORMAL_ARRAY);
}
if ((components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
if ((m_components & VB_HAS_NRM1) != (s_prevcomponents & VB_HAS_NRM1))
{
if (components & VB_HAS_NRM1) {
if (m_components & VB_HAS_NRM1) {
glEnableVertexAttribArray(SHADER_NORM1_ATTRIB);
glEnableVertexAttribArray(SHADER_NORM2_ATTRIB);
}
@ -260,9 +259,9 @@ void GLVertexFormat::EnableComponents(u32 components)
// color
for (int i = 0; i < 2; ++i)
{
if ((components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
if ((m_components & (VB_HAS_COL0 << i)) != (s_prevcomponents & (VB_HAS_COL0 << i)))
{
if (components & (VB_HAS_COL0 << i))
if (m_components & (VB_HAS_COL0 << i))
glEnableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
else
glDisableClientState(i ? GL_SECONDARY_COLOR_ARRAY : GL_COLOR_ARRAY);
@ -272,16 +271,16 @@ void GLVertexFormat::EnableComponents(u32 components)
// tex
for (int i = 0; i < 8; ++i)
{
if ((components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
if ((m_components & (VB_HAS_UV0 << i)) != (s_prevcomponents & (VB_HAS_UV0 << i)))
{
glClientActiveTexture(GL_TEXTURE0 + i);
if (components & (VB_HAS_UV0 << i))
if (m_components & (VB_HAS_UV0 << i))
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
else
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
s_prevcomponents = components;
s_prevcomponents = m_components;
}
}

View File

@ -17,12 +17,16 @@
#include "GLUtil.h"
#include <string.h>
#include "RasterFont.h"
// globals
const GLubyte rasters[][13] = {
static const u32 char_width = 8;
static const u32 char_height = 13;
static const u32 char_offset = 32;
static const u32 char_count = 95;
const u8 rasters[char_count][char_height] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36},
@ -120,104 +124,163 @@ const GLubyte rasters[][13] = {
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x8f, 0xf1, 0x60, 0x00, 0x00, 0x00}
};
static const char *s_vertex_shader =
"attribute vec2 vertexPosition;\n"
"attribute vec2 texturePosition;\n"
"varying vec2 tpos;\n"
"void main(void) {\n"
" gl_Position = vec4(vertexPosition,0,1);\n"
" tpos = texturePosition;\n"
"}\n";
static const char *s_fragment_shader =
"#extension GL_ARB_texture_rectangle : enable\n"
"uniform sampler2DRect textureSampler;\n"
"uniform vec4 color;\n"
"varying vec2 tpos;\n"
"void main(void) {\n"
" gl_FragColor = texture2DRect(textureSampler,tpos) * color;\n"
"}\n";
RasterFont::RasterFont()
{
// set GL modes
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// create the raster font
fontOffset = glGenLists(128);
for (int i = 32; i < 127; i++) {
glNewList(i + fontOffset, GL_COMPILE);
glBitmap(8, 13, 0.0f, 2.0f, 10.0f, 0.0f, rasters[i - 32]);
glEndList();
// generate the texture
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_RECTANGLE, texture);
u32* texture_data = new u32[char_width*char_count*char_height];
for(u32 y=0; y<char_height; y++) {
for(u32 c=0; c<char_count; c++) {
for(u32 x=0; x<char_width; x++) {
bool pixel = rasters[c][y] & (1<<(char_width-x-1));
texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
}
}
}
temp_buffer = new char[TEMP_BUFFER_SIZE];
glTexImage2D(GL_TEXTURE_RECTANGLE, 0, GL_RGBA, char_width*char_count, char_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
delete [] texture_data;
// generate shader
shader_program = OpenGL_CompileProgram(s_vertex_shader, s_fragment_shader);
// bound uniforms
glUseProgram(shader_program);
glUniform1i(glGetUniformLocation(shader_program,"textureSampler"), 0); // GL_TEXTURE0
uniform_color_id = glGetUniformLocation(shader_program,"color");
glUniform4f(uniform_color_id, 1, 1, 1, 1);
cached_color = -1;
glUseProgram(0);
// generate VBO & VAO
glGenBuffers(1, &VBO);
glGenVertexArrays(1, &VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindVertexArray(VAO);
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "vertexPosition"));
glVertexAttribPointer(glGetAttribLocation(shader_program, "vertexPosition"), 2, GL_FLOAT, 0, sizeof(GLfloat)*4, NULL);
glEnableVertexAttribArray(glGetAttribLocation(shader_program, "texturePosition"));
glVertexAttribPointer(glGetAttribLocation(shader_program, "texturePosition"), 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
RasterFont::~RasterFont()
{
glDeleteLists(fontOffset, 128);
delete [] temp_buffer;
glDeleteTextures(1, &texture);
glDeleteBuffers(1, &VBO);
glDeleteVertexArrays(1, &VAO);
glDeleteProgram(shader_program);
}
void RasterFont::printString(const char *s, double x, double y, double z)
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight, u32 color)
{
int length = (int)strlen(s);
int length = (int)strlen(text);
if (!length)
return;
if (length >= TEMP_BUFFER_SIZE)
length = TEMP_BUFFER_SIZE - 1;
// Sanitize string to avoid GL errors.
char *s2 = temp_buffer;
memcpy(s2, s, length);
s2[length] = 0;
for (int i = 0; i < length; i++) {
if (s2[i] < 32 || s2[i] > 126)
s2[i] = '!';
}
// go to the right spot
glRasterPos3d(x, y, z);
GL_REPORT_ERRORD();
glPushAttrib (GL_LIST_BIT);
glListBase(fontOffset);
glCallLists((GLsizei)strlen(s2), GL_UNSIGNED_BYTE, (GLubyte *) s2);
GL_REPORT_ERRORD();
glPopAttrib();
GL_REPORT_ERRORD();
}
void RasterFont::printCenteredString(const char *s, double y, int screen_width, double z)
{
int length = (int)strlen(s);
int x = (int)(screen_width/2.0 - (length/2.0)*char_width);
printString(s, x, y, z);
}
void RasterFont::printMultilineText(const char *text, double start_x, double start_y, double z, int bbWidth, int bbHeight)
{
double x = start_x;
double y = start_y;
char temp[1024];
char *t = temp;
while (*text)
{
if (*text == '\n')
{
*t = 0;
printString(temp, x, y, z);
y -= char_height * 2.0f / bbHeight;
return; // nothing to do
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, length*4*6*sizeof(GLfloat), NULL, GL_STREAM_DRAW);
GLfloat *vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
int usage = 0;
GLfloat delta_x = 2*char_width/GLfloat(bbWidth);
GLfloat delta_y = 2*char_height/GLfloat(bbHeight);
GLfloat border_x = 1*2/GLfloat(bbWidth);
GLfloat border_y = 2*2/GLfloat(bbHeight);
GLfloat x = start_x;
GLfloat y = start_y;
for(int i=0; i<length; i++) {
u8 c = text[i];
if(c == '\n') {
x = start_x;
t = temp;
y -= delta_y + border_y;
continue;
}
else if (*text == '\r')
{
t = temp;
// do not print spaces, they can be skipped easyly
if(c == ' ') {
x += delta_x + border_x;
continue;
}
else if (*text == '\t')
{
//todo: add tabs every something like 4*char_width
*t = 0;
int cpos = (int)strlen(temp);
int newpos = (cpos + 4) & (~3);
printString(temp, x, y, z);
x = start_x + (char_width*newpos) * 2.0f / bbWidth;
t = temp;
*t++ = ' ';
}
else
*t++ = *text;
text++;
if(c < char_offset || c >= char_count+char_offset) continue;
vertices[usage++] = x;
vertices[usage++] = y;
vertices[usage++] = (c-char_offset)*char_width;
vertices[usage++] = 0;
vertices[usage++] = x+delta_x;
vertices[usage++] = y;
vertices[usage++] = (c-char_offset+1)*char_width;
vertices[usage++] = 0;
vertices[usage++] = x+delta_x;
vertices[usage++] = y+delta_y;
vertices[usage++] = (c-char_offset+1)*char_width;
vertices[usage++] = char_height;
vertices[usage++] = x;
vertices[usage++] = y;
vertices[usage++] = (c-char_offset)*char_width;
vertices[usage++] = 0;
vertices[usage++] = x+delta_x;
vertices[usage++] = y+delta_y;
vertices[usage++] = (c-char_offset+1)*char_width;
vertices[usage++] = char_height;
vertices[usage++] = x;
vertices[usage++] = y+delta_y;
vertices[usage++] = (c-char_offset)*char_width;
vertices[usage++] = char_height;
x += delta_x + border_x;
}
glUnmapBuffer(GL_ARRAY_BUFFER);
// no printable char, so also nothing to do
if(!usage) return;
// ????
if (t != text)
{
*t = 0;
printString(temp, x, y, z);
glUseProgram(shader_program);
if(color != cached_color) {
glUniform4f(uniform_color_id, ((color>>16)&0xff)/255.f,((color>>8)&0xff)/255.f,((color>>0)&0xff)/255.f,((color>>24)&0xff)/255.f);
cached_color = color;
}
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE, texture);
glDrawArrays(GL_TRIANGLES, 0, usage/4);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
}

View File

@ -23,20 +23,16 @@ public:
RasterFont();
~RasterFont(void);
static int debug;
// some useful constants
enum {char_width = 10};
enum {char_height = 15};
// and the happy helper functions
void printString(const char *s, double x, double y, double z=0.0);
void printCenteredString(const char *s, double y, int screen_width, double z=0.0);
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight);
void printMultilineText(const char *text, double x, double y, double z, int bbWidth, int bbHeight, u32 color);
private:
int fontOffset;
char *temp_buffer;
enum {TEMP_BUFFER_SIZE = 64 * 1024};
u32 VBO;
u32 VAO;
u32 texture;
u32 shader_program;
u32 uniform_color_id;
u32 cached_color;
};
#endif // _RASTERFONT_H_

View File

@ -63,6 +63,7 @@
#include "Host.h"
#include "BPFunctions.h"
#include "FPSCounter.h"
#include "ConfigManager.h"
#include "main.h" // Local
#ifdef _WIN32
@ -102,10 +103,14 @@ namespace OGL
// Declarations and definitions
// ----------------------------
int s_fps=0;
static int s_fps = 0;
static GLuint s_ShowEFBCopyRegions_VBO = 0;
static GLuint s_ShowEFBCopyRegions_VAO = 0;
static GLuint s_Swap_VBO = 0;
static GLuint s_Swap_VAO[2];
static TargetRectangle s_cached_targetRc;
RasterFont* s_pfont = NULL;
static RasterFont* s_pfont = NULL;
// 1 for no MSAA. Use s_MSAASamples > 1 to check for MSAA.
static int s_MSAASamples = 1;
@ -121,9 +126,9 @@ static std::thread scrshotThread;
#endif
// EFB cache related
const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks.
static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up
static const u32 EFB_CACHE_HEIGHT = (EFB_HEIGHT + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE;
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
@ -236,7 +241,16 @@ Renderer::Renderer()
OSDInternalH = 0;
s_fps=0;
s_ShowEFBCopyRegions_VBO = 0;
s_Swap_VBO = 0;
s_blendMode = 0;
// should be invalid, so there will be an upload on the first call
s_cached_targetRc.bottom = -1;
s_cached_targetRc.top = -1;
s_cached_targetRc.left = -1;
s_cached_targetRc.right = -1;
InitFPSCounter();
@ -291,6 +305,13 @@ Renderer::Renderer()
bSuccess = false;
}
if (!GLEW_ARB_vertex_array_object)
{
ERROR_LOG(VIDEO, "GPU: OGL ERROR: Need GL_ARB_vertex_array_object.\n"
"GPU: Does your video card support OpenGL 3.0?");
bSuccess = false;
}
s_bHaveFramebufferBlit = strstr(ptoken, "GL_EXT_framebuffer_blit") != NULL;
s_bHaveCoverageMSAA = strstr(ptoken, "GL_NV_framebuffer_multisample_coverage") != NULL;
@ -319,8 +340,8 @@ 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__
@ -359,16 +380,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
@ -387,17 +406,46 @@ Renderer::Renderer()
bSuccess = false;
s_pfont = new RasterFont();
// creating buffers
glGenBuffers(1, &s_ShowEFBCopyRegions_VBO);
glGenVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
glBindVertexArray( s_ShowEFBCopyRegions_VAO );
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer (3, GL_FLOAT, sizeof(GLfloat)*5, (GLfloat*)NULL+2);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*5, NULL);
glGenBuffers(1, &s_Swap_VBO);
glGenVertexArrays(2, s_Swap_VAO);
glBindBuffer(GL_ARRAY_BUFFER, s_Swap_VBO);
glBindVertexArray(s_Swap_VAO[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 7*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 7*sizeof(GLfloat), (GLfloat*)NULL+3);
glBindVertexArray(s_Swap_VAO[1]);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 7*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 7*sizeof(GLfloat), (GLfloat*)NULL+3);
glClientActiveTexture(GL_TEXTURE1);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 7*sizeof(GLfloat), (GLfloat*)NULL+5);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glStencilFunc(GL_ALWAYS, 0, 0);
glBlendFunc(GL_ONE, GL_ONE);
glViewport(0, 0, GetTargetWidth(), GetTargetHeight()); // Reset The Current Viewport
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
@ -414,11 +462,6 @@ Renderer::Renderer()
glBlendColorEXT(0, 0, 0, 0.5f);
glClearDepth(1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// legacy multitexturing: select texture channel only.
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
@ -434,6 +477,13 @@ Renderer::~Renderer()
{
g_Config.bRunning = false;
UpdateActiveConfig();
glDeleteBuffers(1, &s_ShowEFBCopyRegions_VBO);
glDeleteVertexArrays(1, &s_ShowEFBCopyRegions_VAO);
glDeleteBuffers(1, &s_Swap_VBO);
glDeleteVertexArrays(2, s_Swap_VAO);
s_ShowEFBCopyRegions_VBO = 0;
delete s_pfont;
s_pfont = 0;
@ -449,7 +499,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;
@ -458,6 +508,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());
@ -470,9 +523,15 @@ void Renderer::DrawDebugInfo()
// Set Line Size
glLineWidth(3.0f);
glBegin(GL_LINES);
// 2*Coords + 3*Color
glBindBuffer(GL_ARRAY_BUFFER, s_ShowEFBCopyRegions_VBO);
glBufferData(GL_ARRAY_BUFFER, stats.efb_regions.size() * sizeof(GLfloat) * (2+3)*2*6, NULL, GL_STREAM_DRAW);
GLfloat *Vertices = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// Draw EFB copy regions rectangles
int a = 0;
GLfloat color[3] = {0.0f, 1.0f, 1.0f};
for (std::vector<EFBRectangle>::const_iterator it = stats.efb_regions.begin();
it != stats.efb_regions.end(); ++it)
{
@ -483,22 +542,97 @@ void Renderer::DrawDebugInfo()
GLfloat x2 = (GLfloat) -1.0f + ((GLfloat)it->right / halfWidth);
GLfloat y2 = (GLfloat) 1.0f - ((GLfloat)it->bottom / halfHeight);
// Draw shadow of rect
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2f(x, y - 0.01); glVertex2f(x2, y - 0.01);
glVertex2f(x, y2 - 0.01); glVertex2f(x2, y2 - 0.01);
glVertex2f(x + 0.005, y); glVertex2f(x + 0.005, y2);
glVertex2f(x2 + 0.005, y); glVertex2f(x2 + 0.005, y2);
// Draw rect
glColor3f(0.0f, 1.0f, 1.0f);
glVertex2f(x, y); glVertex2f(x2, y);
glVertex2f(x, y2); glVertex2f(x2, y2);
glVertex2f(x, y); glVertex2f(x, y2);
glVertex2f(x2, y); glVertex2f(x2, y2);
Vertices[a++] = x;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x2;
Vertices[a++] = y;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
Vertices[a++] = x;
Vertices[a++] = y2;
Vertices[a++] = color[0];
Vertices[a++] = color[1];
Vertices[a++] = color[2];
// TO DO: build something nicer here
GLfloat temp = color[0];
color[0] = color[1];
color[1] = color[2];
color[2] = temp;
}
glEnd();
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindVertexArray( s_ShowEFBCopyRegions_VAO );
glDrawArrays(GL_LINES, 0, stats.efb_regions.size() * 2*6);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// Restore Line Size
glLineWidth(lSize);
@ -523,18 +657,20 @@ 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);
0, nBackbufferWidth, nBackbufferHeight, color);
GL_REPORT_ERRORD();
glDisable(GL_BLEND);
}
TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
@ -919,7 +1055,7 @@ void Renderer::SetBlendMode(bool forceUpdate)
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)
{
@ -939,7 +1075,7 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
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)
{
@ -955,8 +1091,13 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
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
@ -965,7 +1106,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();
@ -996,7 +1137,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;
@ -1010,21 +1158,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();
@ -1050,43 +1190,44 @@ void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight,cons
// Render to the real buffer now.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch to the window backbuffer
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
if (applyShader)
{
glBegin(GL_QUADS);
glTexCoord2f(targetRc.left, targetRc.bottom);
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 0);
glVertex2f(-1, -1);
glTexCoord2f(targetRc.left, targetRc.top);
glMultiTexCoord2fARB(GL_TEXTURE1, 0, 1);
glVertex2f(-1, 1);
if(!( s_cached_targetRc == targetRc)) {
GLfloat vertices[] = {
-1.0f, -1.0f, 1.0f,
(GLfloat)targetRc.left, (GLfloat)targetRc.bottom,
0.0f, 0.0f,
-1.0f, 1.0f, 1.0f,
(GLfloat)targetRc.left, (GLfloat)targetRc.top,
0.0f, 1.0f,
1.0f, 1.0f, 1.0f,
(GLfloat)targetRc.right, (GLfloat)targetRc.top,
1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
(GLfloat)targetRc.right, (GLfloat)targetRc.bottom,
1.0f, 0.0f
};
glBindBuffer(GL_ARRAY_BUFFER, s_Swap_VBO);
glBufferData(GL_ARRAY_BUFFER, 4*7*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
s_cached_targetRc = targetRc;
}
glBindVertexArray(s_Swap_VAO[applyShader]);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glTexCoord2f(targetRc.right, targetRc.top);
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 1);
glVertex2f( 1, 1);
glTexCoord2f(targetRc.right, targetRc.bottom);
glMultiTexCoord2fARB(GL_TEXTURE1, 1, 0);
glVertex2f( 1, -1);
glEnd();
// TODO: this after merging with graphic_update
glBindVertexArray(0);
if(applyShader)
ProgramShaderCache::SetBothShaders(0, 0);
}
else
{
glBegin(GL_QUADS);
glTexCoord2f(targetRc.left, targetRc.bottom);
glVertex2f(-1, -1);
glTexCoord2f(targetRc.left, targetRc.top);
glVertex2f(-1, 1);
glTexCoord2f(targetRc.right, targetRc.top);
glVertex2f( 1, 1);
glTexCoord2f(targetRc.right, targetRc.bottom);
glVertex2f( 1, -1);
glEnd();
}
}
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
@ -1096,7 +1237,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;
@ -1107,16 +1248,16 @@ 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 || w != flipped_trc.GetWidth() ||
h != flipped_trc.GetHeight())
{
if (frame_data) delete[] frame_data;
w = dst_rect.GetWidth();
h = dst_rect.GetHeight();
w = flipped_trc.GetWidth();
h = flipped_trc.GetHeight();
frame_data = new char[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);
if (GL_REPORT_ERROR() == GL_NO_ERROR && w > 0 && h > 0)
{
if (!bLastFrameDumped)
@ -1171,11 +1312,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();
w = GetTargetRectangle().GetWidth();
h = GetTargetRectangle().GetHeight();
frame_data = new char[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);
if (GL_REPORT_ERROR() == GL_NO_ERROR)
{
if (!bLastFrameDumped)
@ -1214,24 +1355,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 w = (fbWidth < 1 || fbWidth > MAX_XFB_WIDTH) ? MAX_XFB_WIDTH : fbWidth;
unsigned int h = (fbHeight < 1 || fbHeight > MAX_XFB_HEIGHT) ? MAX_XFB_HEIGHT : fbHeight;
FramebufferManagerBase::SetLastXfbWidth(w);
FramebufferManagerBase::SetLastXfbHeight(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;
@ -1242,11 +1381,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);
@ -1278,7 +1415,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();

View File

@ -57,6 +57,13 @@
namespace OGL
{
struct VBOCache {
GLuint vbo;
GLuint vao;
TargetRectangle targetSource;
};
static std::map<u64,VBOCache> s_VBO;
static u32 s_TempFramebuffer = 0;
static const GLint c_MinLinearFilter[8] = {
@ -107,6 +114,8 @@ TextureCache::TCacheEntry::~TCacheEntry()
TextureCache::TCacheEntry::TCacheEntry()
{
glGenTextures(1, &texture);
currmode.hex = 0;
currmode1.hex = 0;
GL_REPORT_ERRORD();
}
@ -119,7 +128,9 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage)
// TODO: is this already done somewhere else?
TexMode0 &tm0 = bpmem.tex[stage >> 2].texMode0[stage & 3];
TexMode1 &tm1 = bpmem.tex[stage >> 2].texMode1[stage & 3];
SetTextureParameters(tm0, tm1);
if(currmode.hex != tm0.hex || currmode1.hex != tm1.hex)
SetTextureParameters(tm0, tm1);
}
bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
@ -305,13 +316,59 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
GL_REPORT_ERRORD();
TargetRectangle targetSource = g_renderer->ConvertEFBRectangle(srcRect);
GL_REPORT_ERRORD();
// should be unique enough, if not, vbo will "only" be uploaded to much
u64 targetSourceHash = u64(targetSource.left)<<48 | u64(targetSource.top)<<32 | u64(targetSource.right)<<16 | u64(targetSource.bottom);
std::map<u64, VBOCache>::iterator vbo_it = s_VBO.find(targetSourceHash);
if(vbo_it == s_VBO.end()) {
VBOCache item;
item.targetSource.bottom = -1;
item.targetSource.top = -1;
item.targetSource.left = -1;
item.targetSource.right = -1;
glGenBuffers(1, &item.vbo);
glGenVertexArrays(1, &item.vao);
glBindBuffer(GL_ARRAY_BUFFER, item.vbo);
glBindVertexArray(item.vao);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*4, 0);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*4, (GLfloat*)NULL + 2);
vbo_it = s_VBO.insert(std::pair<u64,VBOCache>(targetSourceHash, item)).first;
}
if(!(vbo_it->second.targetSource == targetSource)) {
GLfloat vertices[] = {
-1.f, 1.f,
(GLfloat)targetSource.left, (GLfloat)targetSource.bottom,
-1.f, -1.f,
(GLfloat)targetSource.left, (GLfloat)targetSource.top,
1.f, -1.f,
(GLfloat)targetSource.right, (GLfloat)targetSource.top,
1.f, 1.f,
(GLfloat)targetSource.right, (GLfloat)targetSource.bottom
};
glBindBuffer(GL_ARRAY_BUFFER, vbo_it->second.vbo);
glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
vbo_it->second.targetSource = targetSource;
}
glBegin(GL_QUADS);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
glEnd();
glBindVertexArray(vbo_it->second.vao);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
GL_REPORT_ERRORD();
@ -358,6 +415,9 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo
void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1)
{
currmode = newmode;
currmode1 = newmode1;
// TODO: not used anywhere
TexMode0 mode = newmode;
//mode1 = newmode1;
@ -389,13 +449,24 @@ void TextureCache::TCacheEntry::SetTextureParameters(const TexMode0 &newmode, co
(float)(1 << g_ActiveConfig.iMaxAnisotropy));
}
TextureCache::TextureCache()
{
}
TextureCache::~TextureCache()
{
if (s_TempFramebuffer)
for(std::map<u64, VBOCache>::iterator it = s_VBO.begin(); it != s_VBO.end(); it++) {
glDeleteBuffers(1, &it->second.vbo);
glDeleteVertexArrays(1, &it->second.vao);
}
s_VBO.clear();
if (s_TempFramebuffer)
{
glDeleteFramebuffersEXT(1, (GLuint*)&s_TempFramebuffer);
s_TempFramebuffer = 0;
}
}
}
void TextureCache::DisableStage(unsigned int stage)

View File

@ -32,6 +32,7 @@ namespace OGL
class TextureCache : public ::TextureCache
{
public:
TextureCache();
static void DisableStage(unsigned int stage);
private:
@ -66,6 +67,8 @@ private:
private:
void SetTextureParameters(const TexMode0 &newmode, const TexMode1 &newmode1);
TexMode0 currmode;
TexMode1 currmode1;
};
~TextureCache();

View File

@ -58,6 +58,14 @@ static FRAGMENTSHADER s_yuyvToRgbProgram;
const u32 NUM_ENCODING_PROGRAMS = 64;
static FRAGMENTSHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
static GLuint s_encode_VBO = 0;
static GLuint s_encode_VAO = 0;
static GLuint s_decode_VBO = 0;
static GLuint s_decode_VAO = 0;
static TargetRectangle s_cached_sourceRc;
static int s_cached_srcWidth = 0;
static int s_cached_srcHeight = 0;
void CreateRgbToYuyvProgram()
{
// Output is BGRA because that is slightly faster than RGBA.
@ -194,9 +202,40 @@ FRAGMENTSHADER &GetOrCreateEncodingShader(u32 format)
void Init()
{
glGenFramebuffersEXT(1, &s_texConvFrameBuffer);
glGenBuffers(1, &s_encode_VBO );
glGenVertexArrays(1, &s_encode_VAO );
glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
glBindVertexArray( s_encode_VAO );
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 4*sizeof(GLfloat), (GLfloat*)NULL + 2);
s_cached_sourceRc.top = -1;
s_cached_sourceRc.bottom = -1;
s_cached_sourceRc.left = -1;
s_cached_sourceRc.right = -1;
glGenBuffers(1, &s_decode_VBO );
glGenVertexArrays(1, &s_decode_VAO );
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
glBindVertexArray( s_decode_VAO );
s_cached_srcWidth = -1;
s_cached_srcHeight = -1;
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*4, NULL);
glClientActiveTexture(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glGenRenderbuffersEXT(1, &s_dstRenderBuffer);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_dstRenderBuffer);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, renderBufferWidth, renderBufferHeight);
s_srcTextureWidth = 0;
@ -216,6 +255,10 @@ void Shutdown()
glDeleteTextures(1, &s_srcTexture);
glDeleteRenderbuffersEXT(1, &s_dstRenderBuffer);
glDeleteFramebuffersEXT(1, &s_texConvFrameBuffer);
glDeleteBuffers(1, &s_encode_VBO );
glDeleteVertexArrays(1, &s_encode_VAO );
glDeleteBuffers(1, &s_decode_VBO );
glDeleteVertexArrays(1, &s_decode_VAO );
s_rgbToYuyvProgram.Destroy();
s_yuyvToRgbProgram.Destroy();
@ -265,13 +308,33 @@ void EncodeToRamUsingShader(GLuint srcTexture, const TargetRectangle& sourceRc,
glViewport(0, 0, (GLsizei)dstWidth, (GLsizei)dstHeight);
// Draw...
glBegin(GL_QUADS);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.top); glVertex2f(-1,-1);
glTexCoord2f((float)sourceRc.left, (float)sourceRc.bottom); glVertex2f(-1,1);
glTexCoord2f((float)sourceRc.right, (float)sourceRc.bottom); glVertex2f(1,1);
glTexCoord2f((float)sourceRc.right, (float)sourceRc.top); glVertex2f(1,-1);
glEnd();
GL_REPORT_ERRORD();
if(!(s_cached_sourceRc == sourceRc)) {
GLfloat vertices[] = {
-1.f, -1.f,
(float)sourceRc.left, (float)sourceRc.top,
-1.f, 1.f,
(float)sourceRc.left, (float)sourceRc.bottom,
1.f, 1.f,
(float)sourceRc.right, (float)sourceRc.bottom,
1.f, -1.f,
(float)sourceRc.right, (float)sourceRc.top
};
glBindBuffer(GL_ARRAY_BUFFER, s_encode_VBO );
glBufferData(GL_ARRAY_BUFFER, 4*4*sizeof(GLfloat), vertices, GL_STREAM_DRAW);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
s_cached_sourceRc = sourceRc;
}
glBindVertexArray( s_encode_VAO );
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
GL_REPORT_ERRORD();
// .. and then read back the results.
@ -431,18 +494,41 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
ProgramShaderCache::SetBothShaders(s_yuyvToRgbProgram.glprogid, 0);
GL_REPORT_ERRORD();
glBegin(GL_QUADS);
glTexCoord2f((float)srcFmtWidth, (float)srcHeight); glVertex2f(1,-1);
glTexCoord2f((float)srcFmtWidth, 0); glVertex2f(1,1);
glTexCoord2f(0, 0); glVertex2f(-1,1);
glTexCoord2f(0, (float)srcHeight); glVertex2f(-1,-1);
glEnd();
if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) {
GLfloat vertices[] = {
1.f, -1.f,
(float)srcFmtWidth, (float)srcHeight,
1.f, 1.f,
(float)srcFmtWidth, 0.f,
-1.f, 1.f,
0.f, 0.f,
-1.f, -1.f,
0.f, (float)srcHeight
};
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW);
// TODO: this after merging with graphic_update
glBindBuffer(GL_ARRAY_BUFFER, 0);
s_cached_srcHeight = srcHeight;
s_cached_srcWidth = srcWidth;
}
glBindVertexArray( s_decode_VAO );
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// TODO: this after merging with graphic_update
glBindVertexArray(0);
GL_REPORT_ERRORD();
// reset state
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
TextureCache::DisableStage(0);
TextureCache::DisableStage(0);
VertexShaderManager::SetViewportChanged();

View File

@ -65,9 +65,16 @@ VertexManager::VertexManager()
// max_Index_size = MAXIBUFFERSIZE;
//
//GL_REPORT_ERRORD();
}
glEnableClientState(GL_VERTEX_ARRAY);
GL_REPORT_ERRORD();
void VertexManager::CreateDeviceObjects()
{
}
void VertexManager::DestroyDeviceObjects()
{
}
void VertexManager::Draw()

View File

@ -33,7 +33,8 @@ public:
VertexManager();
NativeVertexFormat* CreateNativeVertexFormat();
void CreateDeviceObjects();
void DestroyDeviceObjects();
private:
void Draw();
// temp

View File

@ -89,7 +89,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"
@ -168,7 +167,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 +180,7 @@ bool VideoBackend::Initialize(void *&window_handle)
// Run from the graphics thread
void VideoBackend::Video_Prepare()
{
OpenGL_MakeCurrent();
GLInterface->MakeCurrent();
g_renderer = new Renderer;
@ -241,7 +241,7 @@ void VideoBackend::Shutdown()
g_renderer = NULL;
g_texture_cache = NULL;
}
OpenGL_Shutdown();
GLInterface->Shutdown();
}
}