diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index b678220598..979f8bad1d 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -108,9 +108,6 @@ void UpdateFPSDisplay(const char *text) { char temp[512]; sprintf(temp, "SVN R%s: GL: %s", SVN_REV_STR, text); -#if defined(_WIN32) - SetWindowText(EmuWindow::GetWnd(), temp); -#endif OpenGL_SetWindowText(temp); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLWindow.h b/Source/Plugins/Plugin_VideoOGL/Src/GLWindow.h new file mode 100644 index 0000000000..125bee832f --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLWindow.h @@ -0,0 +1,35 @@ +#ifndef _GLWINDOW_H +#define _GLWINDOW_H + +#include "Common.h" +#include "Globals.h" +#include "Config.h" +#include "pluginspecs_video.h" + +class GLWindow { + private: + u32 width, height; + public: + /* int screen; + int x, y; + unsigned int depth;*/ + + virtual void SwapBuffers() = 0; + virtual void SetWindowText(const char *text) = 0; + virtual bool PeekMessages() = 0; + virtual void Update() = 0; + virtual bool MakeCurrent() = 0; + virtual void SetSize(u32 newWidth, u32 newHeight) { + width = newWidth; + height = newHeight; + }; + + u32 GetWidth() {return width;} + u32 GetHeight() {return height;} + + // bool GLwindow(SVideoInitialize &_VideoInitialize, int _iwidth, int _iheight) {}; + // setResolution + // resolution iter +}; + +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/SConscript b/Source/Plugins/Plugin_VideoOGL/Src/SConscript index b698d827ed..fe44acfc25 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/SConscript +++ b/Source/Plugins/Plugin_VideoOGL/Src/SConscript @@ -96,6 +96,11 @@ conf.Define('HAVE_XXF86VM', gfxenv['HAVE_XXF86VM']) conf.Finish() +if gfxenv['HAVE_XXF86VM']: + files += [ + 'X11Window.cpp', + ] + # Sanity check if gfxenv['USE_WX'] and not gfxenv['HAVE_WX']: print "Must have wx to use wxgl" diff --git a/Source/Plugins/Plugin_VideoOGL/Src/X11Window.cpp b/Source/Plugins/Plugin_VideoOGL/Src/X11Window.cpp new file mode 100644 index 0000000000..1f9a6fadc9 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/X11Window.cpp @@ -0,0 +1,307 @@ +#include "X11Window.h" + +X11Window::X11Window(int _iwidth, int _iheight) { + int _twidth, _theight; + if(g_Config.bFullscreen) { + if(strlen(g_Config.iFSResolution) > 1) { + sscanf(g_Config.iFSResolution, "%dx%d", &_twidth, &_theight); + } + else { // No full screen reso set, fall back to default { + _twidth = _iwidth; + _theight = _iheight; + } + } else {// Going Windowed + if(strlen(g_Config.iWindowedRes) > 1) { + sscanf(g_Config.iWindowedRes, "%dx%d", &_twidth, &_theight); + } + else { // No Window reso set, fall back to default + _twidth = _iwidth; + _theight = _iheight; + } + } + + SetSize(_twidth, _theight); + + + // --------------------------------------------------------------------------------------- + // Control window size and picture scaling + // ------------------ + // nBackbufferWidth and nBackbufferHeight = Screen resolution from ini, or 640x480 + // See OpenGL_Update() for documentation of the other variables + // ------------------ + nBackbufferWidth = _twidth; + nBackbufferHeight = _theight; + + float FactorW = 640.0f / (float)nBackbufferWidth; + float FactorH = 480.0f / (float)nBackbufferHeight; + float Max = (FactorW < FactorH) ? FactorH : FactorW; + + if(g_Config.bStretchToFit) { + MValueX = 1.0f / FactorW; + MValueY = 1.0f / FactorH; + nXoff = 0; + nYoff = 0; + } else { + MValueX = 1.0f / Max; + MValueY = 1.0f / Max; + nXoff = (int)((nBackbufferWidth - (640 * MValueX)) / 2); + nYoff = (int)((nBackbufferHeight - (480 * MValueY)) / 2); + } + + XVisualInfo *vi; + Colormap cmap; + int dpyWidth, dpyHeight; + int glxMajorVersion, glxMinorVersion; + int vidModeMajorVersion, vidModeMinorVersion; + Atom wmDelete; + + // 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, GLX_SAMPLES_ARB, 1, None }; + dpy = XOpenDisplay(0); + g_VideoInitialize.pWindowHandle = (HWND)dpy; + screen = DefaultScreen(dpy); + + fs = g_Config.bFullscreen; //Set to setting in Options + + /* get an appropriate visual */ + vi = glXChooseVisual(dpy, screen, attrListDbl); + if (vi == NULL) { + vi = glXChooseVisual(dpy, screen, attrListSgl); + doubleBuffered = False; + ERROR_LOG("Only Singlebuffered Visual!\n"); + } else { + doubleBuffered = True; + ERROR_LOG("Got Doublebuffered Visual!\n"); + } + + glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion); + ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion); + /* create a GLX context */ + ctx = glXCreateContext(dpy, vi, 0, GL_TRUE); + if(!ctx) { + ERROR_LOG("Couldn't Create GLX context.Quit"); + exit(0); // TODO: Don't bring down entire Emu + } + + /* create a color map */ + cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), + vi->visual, AllocNone); + attr.colormap = cmap; + attr.border_pixel = 0; + + // get a connection + XF86VidModeQueryVersion(dpy, &vidModeMajorVersion, &vidModeMinorVersion); + + if (fs) { + + XF86VidModeModeInfo **modes = NULL; + int modeNum = 0; + int bestMode = 0; + + // set best mode to current + bestMode = 0; + ERROR_LOG("XF86VidModeExtension-Version %d.%d\n", vidModeMajorVersion, vidModeMinorVersion); + XF86VidModeGetAllModeLines(dpy, screen, &modeNum, &modes); + + if (modeNum > 0 && modes != NULL) { + /* save desktop-resolution before switching modes */ + deskMode = *modes[0]; + /* look for mode with requested resolution */ + for (int i = 0; i < modeNum; i++) { + if ((modes[i]->hdisplay == _twidth) && + (modes[i]->vdisplay == _theight)) { + bestMode = i; + } + } + + XF86VidModeSwitchToMode(dpy, screen, modes[bestMode]); + XF86VidModeSetViewPort(dpy, screen, 0, 0); + dpyWidth = modes[bestMode]->hdisplay; + dpyHeight = modes[bestMode]->vdisplay; + ERROR_LOG("Resolution %dx%d\n", dpyWidth, dpyHeight); + XFree(modes); + + /* create a fullscreen window */ + attr.override_redirect = True; + attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask; + win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, + dpyWidth, dpyHeight, 0, vi->depth, InputOutput, + vi->visual, CWBorderPixel | CWColormap | + CWEventMask | CWOverrideRedirect, &attr); + XWarpPointer(dpy, None, win, 0, 0, 0, 0, 0, 0); + XMapRaised(dpy, win); + XGrabKeyboard(dpy, win, True, GrabModeAsync, + GrabModeAsync, CurrentTime); + XGrabPointer(dpy, win, True, ButtonPressMask, + GrabModeAsync, GrabModeAsync, win, None, CurrentTime); + } + else { + ERROR_LOG("Failed to start fullscreen. If you received the \n" + "\"XFree86-VidModeExtension\" extension is missing, add\n" + "Load \"extmod\"\n" + "to your X configuration file (under the Module Section)\n"); + fs = 0; + } + } + + if (!fs) { + + // create a window in window mode + attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | + KeyReleaseMask | ButtonReleaseMask | + StructureNotifyMask | ResizeRedirectMask; + win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, _twidth, + _theight, 0, vi->depth, InputOutput, vi->visual, + CWBorderPixel | CWColormap | CWEventMask, &attr); + // only set window title and handle wm_delete_events if in windowed mode + wmDelete = XInternAtom(dpy, "WM_DELETE_WINDOW", True); + XSetWMProtocols(dpy, win, &wmDelete, 1); + XSetStandardProperties(dpy, win, "GPU", + "GPU", None, NULL, 0, NULL); + XMapRaised(dpy, win); + } +} + +X11Window::~X11Window() { + if (ctx) { + if (!glXMakeCurrent(dpy, None, NULL)) { + ERROR_LOG("Could not release drawing context.\n"); + } + XUnmapWindow(dpy, win); + glXDestroyContext(dpy, ctx); + XCloseDisplay(dpy); + ctx = NULL; + } + /* switch back to original desktop resolution if we were in fs */ + if (dpy != NULL) { + if (fs) { + XF86VidModeSwitchToMode(dpy, screen, &deskMode); + XF86VidModeSetViewPort(dpy, screen, 0, 0); + } + } +} + +void X11Window::SwapBuffers() { + glXSwapBuffers(dpy, win); +} + +void X11Window::SetWindowText(const char *text) { + /** + * Tell X to ask the window manager to set the window title. (X + * itself doesn't provide window title functionality.) + */ + XStoreName(dpy, win, text); +} + +bool X11Window::PeekMessages() { + // TODO: implement + return false; +} +void X11Window::Update() { + // We just check all of our events here + XEvent event; + KeySym key; + static bool ShiftPressed = false; + static bool ControlPressed = false; + static int FKeyPressed = -1; + int x,y; + u32 w,h,depth; + + int num_events; + for (num_events = XPending(dpy);num_events > 0;num_events--) { + XNextEvent(dpy, &event); + switch(event.type) { + case KeyRelease: + key = XLookupKeysym((XKeyEvent*)&event, 0); + if(key >= XK_F1 && key <= XK_F9) { + g_VideoInitialize.pKeyPress(FKeyPressed, ShiftPressed, ControlPressed); + FKeyPressed = -1; + } else { + if(key == XK_Shift_L || key == XK_Shift_R) + ShiftPressed = false; + else if(key == XK_Control_L || key == XK_Control_R) + ControlPressed = false; + else + XPutBackEvent(dpy, &event); + } + break; + case KeyPress: + key = XLookupKeysym((XKeyEvent*)&event, 0); + if(key >= XK_F1 && key <= XK_F9) + FKeyPressed = key - 0xff4e; + else { + if(key == XK_Shift_L || key == XK_Shift_R) + ShiftPressed = true; + else if(key == XK_Control_L || key == XK_Control_R) + ControlPressed = true; + else + XPutBackEvent(dpy, &event); + } + break; + case ButtonPress: + case ButtonRelease: + XPutBackEvent(dpy, &event); + break; + case ConfigureNotify: + Window winDummy; + unsigned int borderDummy; + XGetGeometry(dpy, win, &winDummy, &x, &y, + &w, &h, &borderDummy, &depth); + SetSize(w, h); + nBackbufferWidth = w; + nBackbufferHeight = h; + break; + case ClientMessage: //TODO: We aren't reading this correctly, It could be anything, highest chance is that it's a close event though + Video_Shutdown(); // Calling from here since returning false does nothing + return; + break; + default: + //TODO: Should we put the event back if we don't handle it? + // I think we handle all the needed ones, the rest shouldn't matter + // But to be safe, let's but them back anyway + //XPutBackEvent(dpy, &event); + break; + } + } + return; +} + +bool X11Window::MakeCurrent() { + + Window winDummy; + unsigned int borderDummy; + int x,y; + u32 w,h,depth; + // connect the glx-context to the window + glXMakeCurrent(dpy, win, ctx); + XGetGeometry(dpy, win, &winDummy, &x, &y, + &w, &h, &borderDummy, &depth); + SetSize(w, h); + ERROR_LOG("GLWin Depth %d", depth); + if (glXIsDirect(dpy, ctx)) + ERROR_LOG("you have Direct Rendering!"); + else + ERROR_LOG("no Direct Rendering possible!"); + + // better for pad plugin key input (thc) + XSelectInput(dpy, win, ExposureMask | KeyPressMask | ButtonPressMask | + KeyReleaseMask | ButtonReleaseMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask); + + return true; +} diff --git a/Source/Plugins/Plugin_VideoOGL/Src/X11Window.h b/Source/Plugins/Plugin_VideoOGL/Src/X11Window.h new file mode 100644 index 0000000000..19c2708672 --- /dev/null +++ b/Source/Plugins/Plugin_VideoOGL/Src/X11Window.h @@ -0,0 +1,40 @@ +#ifndef _X11WINDOW_H +#define _X11WINDOW_H + +#include "GLWindow.h" +#include +#include + +#include +#include +#include + +#include + +class X11Window : public GLWindow +{ +public: + int screen; + Window win; + Display *dpy; + GLXContext ctx; + XSetWindowAttributes attr; + Bool fs; + Bool doubleBuffered; + XF86VidModeModeInfo deskMode; + int nBackbufferWidth, nBackbufferHeight; + int nXoff, nYoff; // screen offset + // Since it can Stretch to fit Window, we need two different multiplication values + float MValueX, MValueY; + + virtual void SwapBuffers(); + virtual void SetWindowText(const char *text); + virtual bool PeekMessages(); + virtual void Update(); + virtual bool MakeCurrent(); + + ~X11Window(); + X11Window(int _iwidth, int _iheight); +}; + +#endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index af9d3c9b62..ed852179a7 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -152,8 +152,8 @@ void DllConfig(HWND _hParent) ConfigDialog frame(NULL); g_Config.Load(); - frame.ShowModal() -; + frame.ShowModal(); + #elif defined(HAVE_X11) && HAVE_X11 && defined(HAVE_XXF86VM) &&\ HAVE_XXF86VM && defined(HAVE_WX) && HAVE_WX