mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 21:30:19 -06:00
Initial megacommit.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
446
Source/Plugins/Plugin_VideoOGL/Src/GLInit.cpp
Normal file
446
Source/Plugins/Plugin_VideoOGL/Src/GLInit.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
// 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"
|
||||
#ifdef _WIN32
|
||||
#include "EmuWindow.h"
|
||||
#endif
|
||||
#include "GLInit.h"
|
||||
|
||||
|
||||
// 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);
|
||||
#else
|
||||
glXSwapBuffers(GLWin.dpy, GLWin.win);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGL_SetWindowText(const char *text)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
SetWindowText(EmuWindow::GetWnd(), text);
|
||||
#else
|
||||
// TODO
|
||||
#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;
|
||||
#else
|
||||
XEvent event;
|
||||
while (XPending(GLWin.dpy) > 0) {
|
||||
XNextEvent(GLWin.dpy, &event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
OpenGL_SetWindowText(text);
|
||||
}
|
||||
|
||||
|
||||
bool OpenGL_Create(SVideoInitialize &_VideoInitialize, int _width, int _height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
EmuWindow::SetSize(_width, _height);
|
||||
#endif
|
||||
|
||||
nBackbufferWidth = _width;
|
||||
nBackbufferHeight = _height;
|
||||
|
||||
// change later
|
||||
s_nTargetWidth = 640<<g_AAx;
|
||||
s_nTargetHeight = 480<<g_AAy;
|
||||
|
||||
g_VideoInitialize.pPeekMessages = &Callback_PeekMessages;
|
||||
g_VideoInitialize.pUpdateFPSDisplay = &UpdateFPSDisplay;
|
||||
|
||||
#ifdef _WIN32
|
||||
// create the window
|
||||
if (g_VideoInitialize.pWindowHandle == NULL) {
|
||||
// create the window
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Please wait...");
|
||||
if (g_VideoInitialize.pWindowHandle == NULL) {
|
||||
SysMessage("failed to create window");
|
||||
return false;
|
||||
}
|
||||
EmuWindow::Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Please wait...");
|
||||
}
|
||||
|
||||
GLuint PixelFormat; // Holds The Results After Searching For A Match
|
||||
DWORD dwExStyle; // Window Extended Style
|
||||
DWORD dwStyle; // Window Style
|
||||
|
||||
RECT rcdesktop;
|
||||
GetWindowRect(GetDesktopWindow(), &rcdesktop);
|
||||
|
||||
if (g_Config.bFullscreen) {
|
||||
nBackbufferWidth = rcdesktop.right - rcdesktop.left;
|
||||
nBackbufferHeight = rcdesktop.bottom - rcdesktop.top;
|
||||
|
||||
DEVMODE dmScreenSettings;
|
||||
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
|
||||
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
|
||||
dmScreenSettings.dmPelsWidth = nBackbufferWidth;
|
||||
dmScreenSettings.dmPelsHeight = nBackbufferHeight;
|
||||
dmScreenSettings.dmBitsPerPel = 32;
|
||||
dmScreenSettings.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
|
||||
|
||||
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
|
||||
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
|
||||
{
|
||||
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
|
||||
g_Config.bFullscreen = false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// change to default resolution
|
||||
ChangeDisplaySettings(NULL, 0);
|
||||
}
|
||||
|
||||
if (g_Config.bFullscreen) {
|
||||
dwExStyle=WS_EX_APPWINDOW;
|
||||
dwStyle=WS_POPUP;
|
||||
ShowCursor(FALSE);
|
||||
}
|
||||
else {
|
||||
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
dwStyle=WS_OVERLAPPEDWINDOW;
|
||||
}
|
||||
|
||||
RECT rc;
|
||||
rc.left = 0; rc.top = 0;
|
||||
rc.right = nBackbufferWidth; rc.bottom = nBackbufferHeight;
|
||||
AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
|
||||
int X = (rcdesktop.right-rcdesktop.left)/2 - (rc.right-rc.left)/2;
|
||||
int Y = (rcdesktop.bottom-rcdesktop.top)/2 - (rc.bottom-rc.top)/2;
|
||||
|
||||
// SetWindowPos(EmuWindow::GetWnd(), NULL, X, Y, rc.right-rc.left, rc.bottom-rc.top, SWP_NOREPOSITION|SWP_NOZORDER);
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
if (!(hDC=GetDC(EmuWindow::GetWnd()))) {
|
||||
MessageBox(NULL,"(1) Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) {
|
||||
MessageBox(NULL,"(2) Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(hDC,PixelFormat,&pfd)) {
|
||||
MessageBox(NULL,"(3) Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(hRC=wglCreateContext(hDC))) {
|
||||
MessageBox(NULL,"(4) Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
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,
|
||||
None };
|
||||
GLWin.dpy = XOpenDisplay(0);
|
||||
g_VideoInitialize.pWindowHandle = (HWND)GLWin.dpy;
|
||||
GLWin.screen = DefaultScreen(GLWin.dpy);
|
||||
|
||||
GLWin.fs = false; // !!(conf.options & GSOPTION_FULLSCREEN);
|
||||
|
||||
/* get an appropriate visual */
|
||||
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListDbl);
|
||||
if (vi == NULL) {
|
||||
vi = glXChooseVisual(GLWin.dpy, GLWin.screen, attrListSgl);
|
||||
GLWin.doubleBuffered = False;
|
||||
ERROR_LOG("Only Singlebuffered Visual!\n");
|
||||
}
|
||||
else {
|
||||
GLWin.doubleBuffered = True;
|
||||
ERROR_LOG("Got Doublebuffered Visual!\n");
|
||||
}
|
||||
|
||||
glXQueryVersion(GLWin.dpy, &glxMajorVersion, &glxMinorVersion);
|
||||
ERROR_LOG("glX-Version %d.%d\n", glxMajorVersion, glxMinorVersion);
|
||||
/* create a GLX context */
|
||||
GLWin.ctx = glXCreateContext(GLWin.dpy, vi, 0, GL_TRUE);
|
||||
/* create a color map */
|
||||
cmap = XCreateColormap(GLWin.dpy, RootWindow(GLWin.dpy, vi->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 == _width) && (modes[i]->vdisplay == _height)) {
|
||||
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, _width, _height, 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);
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#else
|
||||
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 );
|
||||
#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<<g_AAx;
|
||||
s_nTargetHeight = 480<<g_AAy; */
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void OpenGL_Shutdown()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (hRC) // Do We Have A Rendering Context?
|
||||
{
|
||||
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
|
||||
{
|
||||
MessageBox(NULL,"Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
|
||||
{
|
||||
MessageBox(NULL,"Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
|
||||
}
|
||||
hRC = NULL; // Set RC To NULL
|
||||
}
|
||||
|
||||
if (hDC && !ReleaseDC(EmuWindow::GetWnd(),hDC)) // Are We Able To Release The DC
|
||||
{
|
||||
MessageBox(NULL,"Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
|
||||
hDC = NULL; // Set DC To NULL
|
||||
}
|
||||
#else // linux
|
||||
if (GLWin.ctx)
|
||||
{
|
||||
if (!glXMakeCurrent(GLWin.dpy, None, NULL))
|
||||
{
|
||||
ERROR_LOG("Could not release drawing context.\n");
|
||||
}
|
||||
glXDestroyContext(GLWin.dpy, GLWin.ctx);
|
||||
GLWin.ctx = NULL;
|
||||
}
|
||||
/* switch back to original desktop resolution if we were in fs */
|
||||
if (GLWin.dpy != NULL) {
|
||||
if (GLWin.fs) {
|
||||
XF86VidModeSwitchToMode(GLWin.dpy, GLWin.screen, &GLWin.deskMode);
|
||||
XF86VidModeSetViewPort(GLWin.dpy, GLWin.screen, 0, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user