pcsx2/plugins/zzogl-pg/opengl/GLWinX11.cpp

285 lines
7.5 KiB
C++
Raw Normal View History

/* ZZ Open GL graphics plugin
* Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
* Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "GS.h"
#include "zerogs.h"
#ifdef GL_X11_WINDOW
#include <X11/Xlib.h>
bool GLWindow::CreateWindow(void *pDisplay)
{
glDisplay = XOpenDisplay(0);
glScreen = DefaultScreen(glDisplay);
if (pDisplay == NULL) return false;
*(Display**)pDisplay = glDisplay;
return true;
}
bool GLWindow::ReleaseWindow()
{
if (context)
{
if (!glXMakeCurrent(glDisplay, None, NULL))
{
ZZLog::Error_Log("Could not release drawing context.");
}
glXDestroyContext(glDisplay, context);
context = NULL;
}
/* switch back to original desktop resolution if we were in fullscreen */
if (glDisplay != NULL)
{
if (fullScreen)
{
XF86VidModeSwitchToMode(glDisplay, glScreen, &deskMode);
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
}
}
return true;
}
void GLWindow::CloseWindow()
{
conf.x = x;
conf.y = y;
SaveConfig();
if (glDisplay != NULL)
{
XCloseDisplay(glDisplay);
glDisplay = NULL;
}
}
bool GLWindow::DisplayWindow(int _width, int _height)
{
int i;
XVisualInfo *vi;
Colormap cmap;
int dpyWidth, dpyHeight;
int glxMajorVersion, glxMinorVersion;
int vidModeMajorVersion, vidModeMinorVersion;
Atom wmDelete;
Window winDummy;
unsigned int borderDummy;
x = conf.x;
y = conf.y;
// 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,
None
};
GLWin.fullScreen = (conf.fullscreen());
/* get an appropriate visual */
vi = glXChooseVisual(glDisplay, glScreen, attrListDbl);
if (vi == NULL)
{
vi = glXChooseVisual(glDisplay, glScreen, attrListSgl);
doubleBuffered = false;
ZZLog::Error_Log("Only Singlebuffered Visual!");
}
else
{
doubleBuffered = true;
ZZLog::Error_Log("Got Doublebuffered Visual!");
}
if (vi == NULL)
{
ZZLog::Error_Log("Failed to get buffered Visual!");
return false;
}
glXQueryVersion(glDisplay, &glxMajorVersion, &glxMinorVersion);
ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
/* create a GLX context */
context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE);
/* create a color map */
cmap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
vi->visual, AllocNone);
attr.colormap = cmap;
attr.border_pixel = 0;
// get a connection
XF86VidModeQueryVersion(glDisplay, &vidModeMajorVersion, &vidModeMinorVersion);
if (fullScreen)
{
XF86VidModeModeInfo **modes = NULL;
int modeNum = 0;
int bestMode = 0;
// set best mode to current
bestMode = 0;
ZZLog::Error_Log("XF86VidModeExtension-Version %d.%d.", vidModeMajorVersion, vidModeMinorVersion);
XF86VidModeGetAllModeLines(glDisplay, glScreen, &modeNum, &modes);
if (modeNum > 0 && modes != NULL)
{
/* save desktop-resolution before switching modes */
deskMode = *modes[0];
/* look for mode with requested resolution */
for (i = 0; i < modeNum; i++)
{
if ((modes[i]->hdisplay == _width) && (modes[i]->vdisplay == _height))
{
bestMode = i;
}
}
XF86VidModeSwitchToMode(glDisplay, glScreen, modes[bestMode]);
XF86VidModeSetViewPort(glDisplay, glScreen, 0, 0);
dpyWidth = modes[bestMode]->hdisplay;
dpyHeight = modes[bestMode]->vdisplay;
ZZLog::Error_Log("Resolution %dx%d.", dpyWidth, dpyHeight);
XFree(modes);
/* create a fullscreen window */
attr.override_redirect = True;
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, dpyWidth, dpyHeight, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect,
&attr);
XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 0, 0);
XMapRaised(glDisplay, glWindow);
XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime);
}
else
{
ZZLog::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)");
fullScreen = false;
}
}
if (!fullScreen)
{
// create a window in window mode
attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask;
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
0, 0, _width, _height, 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(glDisplay, "WM_DELETE_WINDOW", True);
XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1);
XSetStandardProperties(glDisplay, glWindow, "ZZOgl-PG", "ZZOgl-PG", None, NULL, 0, NULL);
XMapRaised(glDisplay, glWindow);
XMoveWindow(glDisplay, glWindow, x, y);
}
// connect the glx-context to the window
glXMakeCurrent(glDisplay, glWindow, context);
XGetGeometry(glDisplay, glWindow, &winDummy, &x, &y, &width, &height, &borderDummy, &depth);
ZZLog::Error_Log("Depth %d", depth);
if (glXIsDirect(glDisplay, context))
ZZLog::Error_Log("You have Direct Rendering!");
else
ZZLog::Error_Log("No Direct Rendering possible!");
// better for pad plugin key input (thc)
XSelectInput(glDisplay, glWindow, ExposureMask | KeyPressMask | KeyReleaseMask |
ButtonPressMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask |
FocusChangeMask);
return true;
}
void GLWindow::SwapGLBuffers()
{
glXSwapBuffers(glDisplay, glWindow);
}
void GLWindow::SetTitle(char *strtitle)
{
XTextProperty prop;
memset(&prop, 0, sizeof(prop));
char* ptitle = strtitle;
if (XStringListToTextProperty(&ptitle, 1, &prop))
XSetWMName(glDisplay, glWindow, &prop);
XFree(prop.value);
}
void GLWindow::ResizeCheck()
{
XEvent event;
while (XCheckTypedEvent(glDisplay, ConfigureNotify, &event))
{
if ((event.xconfigure.width != width) || (event.xconfigure.height != height))
{
ZeroGS::ChangeWindowSize(event.xconfigure.width, event.xconfigure.height);
width = event.xconfigure.width;
height = event.xconfigure.height;
}
if ((event.xconfigure.x != x) || (event.xconfigure.y != y))
{
x = event.xconfigure.x;
y = event.xconfigure.y;
}
}
}
#endif