// Copyright (C) 2003-2008 Dolphin Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ #include "Globals.h" #include "IniFile.h" #ifdef _WIN32 #include "svnrev.h" #include "OS\Win32.h" #endif #include "GLInit.h" #ifdef MACOSX #include "SDL/SDL.h" #endif // Handles OpenGL and the window // screen offset int nBackbufferWidth, nBackbufferHeight; u32 s_nTargetWidth = 0, s_nTargetHeight = 0; u32 g_AAx = 0, g_AAy = 0; #ifndef _WIN32 GLWindow GLWin; #endif #ifdef _WIN32 static HDC hDC = NULL; // Private GDI Device Context static HGLRC hRC = NULL; // Permanent Rendering Context extern HINSTANCE g_hInstance; #endif void OpenGL_SwapBuffers() { #ifdef _WIN32 SwapBuffers(hDC); #elifdef __linux__ glXSwapBuffers(GLWin.dpy, GLWin.win); #else //others SDL_GL_SwapBuffers(); #endif } void OpenGL_SetWindowText(const char *text) { #ifdef _WIN32 SetWindowText(EmuWindow::GetWnd(), text); #elifdef __linux__ /** * 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); #else SDL_WM_SetCaption(text, NULL); #endif } BOOL Callback_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; #elifdef __linux__ XEvent event; while (XPending(GLWin.dpy) > 0) { XNextEvent(GLWin.dpy, &event); } return TRUE; #else //TODO #endif } void UpdateFPSDisplay(const char *text) { #ifdef _WIN32 char temp[512]; sprintf(temp, "SVN R%i: %s", SVN_REV, text); SetWindowText(EmuWindow::GetWnd(), temp); OpenGL_SetWindowText(temp); #else char temp[512]; sprintf(temp, "SVN %s: %s", "Linux", text); //TODO: Set to svn rev // OpenGL_SetWindowText(temp); #endif } bool OpenGL_Create(SVideoInitialize &_VideoInitialize, 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 reso { _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; } } #ifdef _WIN32 EmuWindow::SetSize(_twidth, _theight); #endif nBackbufferWidth = _twidth; nBackbufferHeight = _theight; // change later s_nTargetWidth = 640<screen), vi->visual, AllocNone); GLWin.attr.colormap = cmap; GLWin.attr.border_pixel = 0; // get a connection XF86VidModeQueryVersion(GLWin.dpy, &vidModeMajorVersion, &vidModeMinorVersion); if (GLWin.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(GLWin.dpy, GLWin.screen, &modeNum, &modes); if (modeNum > 0 && modes != NULL) { /* save desktop-resolution before switching modes */ GLWin.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(GLWin.dpy, GLWin.screen, modes[bestMode]); XF86VidModeSetViewPort(GLWin.dpy, GLWin.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 */ GLWin.attr.override_redirect = True; GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), 0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &GLWin.attr); XWarpPointer(GLWin.dpy, None, GLWin.win, 0, 0, 0, 0, 0, 0); XMapRaised(GLWin.dpy, GLWin.win); XGrabKeyboard(GLWin.dpy, GLWin.win, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(GLWin.dpy, GLWin.win, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, GLWin.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"); GLWin.fs = 0; } } if (!GLWin.fs) { //XRootWindow(dpy,screen) //int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2; //int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2; // create a window in window mode GLWin.attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask; GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen), 0, 0, _twidth, _theight, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr); // only set window title and handle wm_delete_events if in windowed mode wmDelete = XInternAtom(GLWin.dpy, "WM_DELETE_WINDOW", True); XSetWMProtocols(GLWin.dpy, GLWin.win, &wmDelete, 1); XSetStandardProperties(GLWin.dpy, GLWin.win, "GPU", "GPU", None, NULL, 0, NULL); XMapRaised(GLWin.dpy, GLWin.win); } #else //SDL fo other OS (osx, bsd, ...) int videoFlags; SDL_Surface *screen; const SDL_VideoInfo *videoInfo; //init sdl video SDL_Init(SDL_INIT_VIDEO); //fetch video info videoInfo = SDL_GetVideoInfo(); //hw o sw ogl ? if (videoInfo->hw_available) videoFlags |= SDL_HWSURFACE; else videoFlags |= SDL_SWSURFACE; //fullscreen or not if(g_Config.bFullscreen) videoFlags |= SDL_FULLSCREEN; //setup ogl to use double buffering SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); screen = SDL_SetVideoMode(_twidth, _theight, 24, SDL_OPENGL|SDL_RESIZABLE); #endif return true; } bool OpenGL_MakeCurrent() { #ifdef _WIN32 if (!wglMakeCurrent(hDC,hRC)) { MessageBox(NULL,"(5) Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION); return false; } #elifdef __linux__ Window winDummy; unsigned int borderDummy; // connect the glx-context to the window glXMakeCurrent(GLWin.dpy, GLWin.win, GLWin.ctx); XGetGeometry(GLWin.dpy, GLWin.win, &winDummy, &GLWin.x, &GLWin.y, &GLWin.width, &GLWin.height, &borderDummy, &GLWin.depth); ERROR_LOG("GLWin Depth %d", GLWin.depth); if (glXIsDirect(GLWin.dpy, GLWin.ctx)) ERROR_LOG("you have Direct Rendering!"); else ERROR_LOG("no Direct Rendering possible!"); // better for pad plugin key input (thc) XSelectInput(GLWin.dpy, GLWin.win, ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask ); #else //TODO #endif return true; } void OpenGL_Update() { #ifdef _WIN32 if (EmuWindow::GetParentWnd()) { RECT rcWindow; GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow); int width = rcWindow.right - rcWindow.left; int height = rcWindow.bottom - rcWindow.top; ::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE); nBackbufferWidth = width; nBackbufferHeight = height; /* u32 TmpAAx = (width / 640) - 1; u32 TmpAAy = (height / 480) - 1; u32 FinalAA = TmpAAx < TmpAAy ? TmpAAx : TmpAAy; g_AAx = FinalAA; g_AAy = FinalAA; s_nTargetWidth = 640<