Show open.cpp syntax highlighted
/***************************************************************************
open.cpp - Open and initialize render window
-------------------
begin : Mon Mar 31 2003
copyright : (C) 2003 by Reality Rift Studios
email : mattias@realityrift.com
***************************************************************************
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the
License.
The Original Code is the NeoEngine, NeoDevOpenGL, open.cpp
The Initial Developer of the Original Code is Mattias Jansson.
Portions created by Mattias Jansson are Copyright (C) 2003
Reality Rift Studios. All Rights Reserved.
***************************************************************************/
#define NEEDGDI
#define __NEED_VECTOR_INT
#include "device.h"
#include "framebuffertarget.h"
#include <neoengine/logstream.h>
using namespace std;
using namespace NeoEngine;
namespace NeoOGL
{
#ifdef WIN32
LONG WINAPI WindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
#define NEOGLDEVICE_WINDOWCLASSNAME "neogldevicewnd"
#endif
#ifdef POSIX
int CmpModes( const void *va, const void *vb )
{
XF86VidModeModeInfo *a = *(XF86VidModeModeInfo**)va;
XF86VidModeModeInfo *b = *(XF86VidModeModeInfo**)vb;
if( a->hdisplay > b->hdisplay)
return -1;
return b->vdisplay - a->vdisplay;
}
XVisualInfo *GetXVisual( Display *pDisplay, const RenderCaps *pkCaps, RenderResolution *pkRes )
{
if( !pkRes->m_uiDepthBits )
pkRes->m_uiDepthBits = 16;
XVisualInfo *pVisualInfo = 0;
int aiConfiguration[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, pkRes->m_uiDepthBits, GLX_RED_SIZE, 5, GLX_GREEN_SIZE, 5, GLX_BLUE_SIZE, 5, None, None, None };
if( pkCaps && pkCaps->IsSet( RenderCaps::STENCILBUFFER ) )
{
if( !pkRes->m_uiStencilBits )
pkRes->m_uiStencilBits = 8;
aiConfiguration[10] = GLX_STENCIL_SIZE;
aiConfiguration[11] = pkRes->m_uiStencilBits;
}
if( !glXQueryExtension( pDisplay, 0, 0 ) )
{
neolog << LogLevel( ERROR ) << "*** No GLX extension found in X server" << endl;
return 0;
}
if( !( pVisualInfo = glXChooseVisual( pDisplay, DefaultScreen( pDisplay ), aiConfiguration ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to get a visual" << endl;
return 0;
}
return pVisualInfo;
}
#endif
bool Device::Open( const RenderWindow &rkWndData )
{
Close();
m_kWindow.m_strWindowName = rkWndData.m_strWindowName;
m_kWindow.m_kResolution = rkWndData.m_kResolution;
m_kWindow.m_uiFsaa = rkWndData.m_uiFsaa;
if( m_kWindow.m_kResolution.m_uiBPP < 15 )
m_kWindow.m_kResolution.m_uiBPP = 16;
else if( m_kWindow.m_kResolution.m_uiBPP > 32 )
m_kWindow.m_kResolution.m_uiBPP = 32;
#ifdef WIN32
if( !rkWndData.m_hWnd )
#elif __APPLE__
if( !rkWndData.m_pWindow )
#elif POSIX
if( !rkWndData.m_Window )
#endif
{
neolog << LogLevel( INFO ) << "Creating rendering window" << endl;
m_kWindow.m_uiFlags |= RenderWindow::DEVICECREATED;
if( rkWndData.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
m_kWindow.m_kCaps.Set( RenderCaps::FULLSCREEN );
#ifdef WIN32
m_kWindow.m_hInstance = GetModuleHandle( 0 );
m_kWindow.m_uiAdapter = rkWndData.m_uiAdapter;
if( !s_bWindowClassRegistered )
{
WNDCLASS wc;
wc.style = CS_OWNDC;
wc.lpfnWndProc = (WNDPROC)WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = (HINSTANCE)m_kWindow.m_hInstance;
wc.hIcon = LoadIcon(0, IDI_WINLOGO);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = 0;
wc.lpszMenuName = 0;
wc.lpszClassName = NEOGLDEVICE_WINDOWCLASSNAME;
if( !RegisterClass( &wc ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to register window class" << endl;
return false;
}
s_bWindowClassRegistered = true;
}
RECT kRect;
kRect.left = 0;
kRect.top = 0;
kRect.right = m_kWindow.m_kResolution.m_uiWidth;
kRect.bottom = m_kWindow.m_kResolution.m_uiHeight;
if( !( m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) ) )
{
AdjustWindowRect( &kRect, WS_OVERLAPPEDWINDOW, FALSE );
neolog << LogLevel( DEBUG ) << " rect [ " << kRect.left << " " << kRect.top << " -> " << kRect.right << " " << kRect.bottom << " ]" << endl;
}
m_kWindow.m_hWnd = CreateWindowEx( m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) ? WS_EX_TOPMOST : 0, NEOGLDEVICE_WINDOWCLASSNAME, m_kWindow.m_strWindowName.c_str(), ( !m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) ? WS_OVERLAPPEDWINDOW : WS_POPUP ) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, kRect.right - kRect.left, kRect.bottom - kRect.top, 0, 0, (HINSTANCE)m_kWindow.m_hInstance, this );
if( !m_kWindow.m_hWnd )
{
neolog << LogLevel( ERROR ) << "*** Unable to create window" << endl;
return false;
}
SetWindowLong( (HWND)m_kWindow.m_hWnd, GWL_USERDATA, (long)this );
SetForegroundWindow( (HWND)m_kWindow.m_hWnd );
//Store desktop resolution
HDC hDeskDC = GetDC( 0 );
m_kWindow.m_kDesktopResolution.m_uiWidth = GetDeviceCaps( hDeskDC, HORZRES );
m_kWindow.m_kDesktopResolution.m_uiHeight = GetDeviceCaps( hDeskDC, VERTRES );
m_kWindow.m_kDesktopResolution.m_uiBPP = GetDeviceCaps( hDeskDC, BITSPIXEL );
ReleaseDC( 0, hDeskDC );
if( m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
{
DEVMODE devMode;
memset( &devMode, 0, sizeof( DEVMODE ) );
devMode.dmSize = sizeof( DEVMODE );
devMode.dmDriverExtra = 0;
devMode.dmBitsPerPel = m_kWindow.m_kResolution.m_uiBPP;
devMode.dmPelsWidth = m_kWindow.m_kResolution.m_uiWidth;
devMode.dmPelsHeight = m_kWindow.m_kResolution.m_uiHeight;
devMode.dmDisplayFrequency = m_kWindow.m_kResolution.m_uiRefreshRate;
devMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
ChangeDisplaySettings( &devMode, CDS_FULLSCREEN | CDS_SET_PRIMARY );
}
#elif __APPLE__
if( !m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
{
Rect rectSize =
{
50, // top offset to avoid menu bar
0,
m_kWindow.m_kResolution.m_uiHeight + 50,
m_kWindow.m_kResolution.m_uiWidth,
};
Str255 strTitle;
CopyCStringToPascal( m_kWindow.m_strWindowName.c_str(), strTitle );
m_kWindow.m_pWindow = NewCWindow( NULL, &rectSize, strTitle, true, kWindowFullZoomGrowDocumentProc, (WindowPtr)-1, true, 0 );
}
#elif POSIX
//Ugly solution!
if( !( m_kWindow.m_pDisplay = XOpenDisplay( 0 ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to open display" << endl;
return false;
}
XVisualInfo *pVisualInfo = GetXVisual( (Display*)m_kWindow.m_pDisplay, &rkWndData.m_kCaps, &m_kWindow.m_kResolution );
if( !pVisualInfo )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to get X visual" << endl;
return false;
}
Colormap ColorMap = XCreateColormap( (Display*) m_kWindow.m_pDisplay, RootWindow( (Display*) m_kWindow.m_pDisplay, pVisualInfo->screen ), pVisualInfo->visual, AllocNone );
XSetWindowAttributes kSetWindowAttributes;
kSetWindowAttributes.colormap = ColorMap;
kSetWindowAttributes.border_pixel = 0;
kSetWindowAttributes.event_mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask | ButtonMotionMask | KeyPressMask | KeyReleaseMask;
m_kWindow.m_Window = (void*)XCreateWindow( (Display*)m_kWindow.m_pDisplay, RootWindow( (Display*)m_kWindow.m_pDisplay, pVisualInfo->screen ), 0, 0, m_kWindow.m_kResolution.m_uiWidth, m_kWindow.m_kResolution.m_uiHeight, 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual, CWBorderPixel | CWColormap | CWEventMask, &kSetWindowAttributes );
XSetStandardProperties( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, m_kWindow.m_strWindowName.c_str(), m_kWindow.m_strWindowName.c_str(), None, 0, 0, 0 );
m_kWindow.m_uiFlags |= RenderWindow::DEVICECREATED;
if( m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
{
XF86VidModeModeLine Modeline;
XF86VidModeModeInfo **ppModes;
XSetWindowAttributes FSAttributes;
int iNum, i;
// Save old video mode
memset( &m_OldMode, 0, sizeof( m_OldMode ) );
XF86VidModeModeLine *tmpMode = (XF86VidModeModeLine*) ( (char*) &m_OldMode + sizeof( m_OldMode.dotclock ) );
XF86VidModeGetModeLine( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), (int*) &m_OldMode.dotclock, tmpMode );
XF86VidModeGetViewPort( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), (int*)&m_kWindow.m_kDesktopResolution.m_uiWidth, (int*)&m_kWindow.m_kDesktopResolution.m_uiHeight );
XF86VidModeGetModeLine( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), &iNum, &Modeline );
//Find and set the closest resolution matching the one we wan't for our game
XF86VidModeGetAllModeLines( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), &iNum, &ppModes );
qsort( ppModes, iNum, sizeof( *ppModes ), CmpModes );
for( i = iNum - 1; i >= 0; --i )
if( ( ppModes[i]->hdisplay == m_kWindow.m_kResolution.m_uiWidth) && ( ppModes[i]->vdisplay == m_kWindow.m_kResolution.m_uiHeight) )
break;
if( i < 0 ) for( i = iNum - 1; i >= 0; --i )
if( ( ppModes[i]->hdisplay >= m_kWindow.m_kResolution.m_uiWidth) && ( ppModes[i]->vdisplay >= m_kWindow.m_kResolution.m_uiHeight) )
break;
if( i < 0 )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Unable to find suitable fullscreen resolution" << endl;
return false;
}
if( ( ppModes[i]->hdisplay != Modeline.hdisplay) || ( ppModes[i]->vdisplay != Modeline.vdisplay) )
XF86VidModeSwitchToMode( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), ppModes[i] );
FSAttributes.override_redirect = true;
FSAttributes.background_pixel = BlackPixel( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ) );
FSAttributes.border_pixel = 0;
FSAttributes.colormap = ColorMap;
//Create a window that covers the screen with black (there is no true fullscreen mode in X, gotta love it =)
m_FSWindow = XCreateWindow( (Display*)m_kWindow.m_pDisplay, RootWindow( (Display*)m_kWindow.m_pDisplay, pVisualInfo->screen ), 0, 0, 32, 32, 0, pVisualInfo->depth, InputOutput, pVisualInfo->visual, CWBackPixel | CWColormap | CWOverrideRedirect, &FSAttributes );
XSelectInput( (Display*)m_kWindow.m_pDisplay, m_FSWindow, StructureNotifyMask );
XMoveWindow( (Display*)m_kWindow.m_pDisplay, m_FSWindow, 0, 0 );
// Should we use Modeline.[h|v]display here instead?
XResizeWindow( (Display*)m_kWindow.m_pDisplay, m_FSWindow, ppModes[i]->hdisplay, ppModes[i]->vdisplay );
XMapRaised( (Display*)m_kWindow.m_pDisplay, m_FSWindow );
//Set the fullscreen window as parent for the game window and make sure we are exclusively grabbing all input
//and constraining the mouse pointer to the game window (FEAR virtual resolutions!)
// Should we use Modeline.[h|v]display here instead?
XReparentWindow( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, m_FSWindow, 0, 0 );//( ppModes[i]->hdisplay - m_kWindow.m_kResolution.m_uiWidth ) / 2, ( ppModes[i]->vdisplay - m_kWindow.m_kResolution.m_uiHeight ) / 2 );
XMapWindow( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window );
if( ( XGrabPointer( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, true, 0, GrabModeAsync, GrabModeAsync, (Window)m_kWindow.m_Window, None, CurrentTime ) != GrabSuccess) || ( XGrabKeyboard( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, true, GrabModeAsync, GrabModeAsync, CurrentTime ) != 0) )
neolog << LogLevel( WARNING ) << "*** Unable to grab input" << endl;
//Make sure mouse is centered
XWarpPointer( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, (Window)m_kWindow.m_Window, 0, 0, m_kWindow.m_kResolution.m_uiWidth, m_kWindow.m_kResolution.m_uiHeight, 0, 0 );
XWarpPointer( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, (Window)m_kWindow.m_Window, 0, 0, m_kWindow.m_kResolution.m_uiWidth, m_kWindow.m_kResolution.m_uiHeight, m_kWindow.m_kResolution.m_uiWidth / 2, m_kWindow.m_kResolution.m_uiHeight / 2 );
//Do some final cleaning and lock the current video mode so that the user doesn't start playing with ctrl+alt+[+]/[-]
XInstallColormap( (Display*)m_kWindow.m_pDisplay, ColorMap );
XSync( (Display*)m_kWindow.m_pDisplay, true );
XF86VidModeLockModeSwitch( (Display*)m_kWindow.m_pDisplay, DefaultScreen( (Display*)m_kWindow.m_pDisplay ), true );
XFree( ppModes );
}
else
{
//We aren't running fullscreen so just draw the game window wherever X wants it
XMapWindow( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window );
}
XFlush( (Display*)m_kWindow.m_pDisplay );
m_WMDeleteWindow = XInternAtom( (Display*)m_kWindow.m_pDisplay, "WM_DELETE_WINDOW", False );
XSetWMProtocols( (Display*)m_kWindow.m_pDisplay, (Window)m_kWindow.m_Window, &m_WMDeleteWindow, 1 );
#endif
}
else
{
#ifdef WIN32
if( !m_kWindow.m_hInstance && !( m_kWindow.m_hInstance = rkWndData.m_hInstance ) )
m_kWindow.m_hInstance = GetModuleHandle( 0 );
m_kWindow.m_hWnd = rkWndData.m_hWnd;
if( !( m_kWindow.m_uiFlags & RenderWindow::USEDIMENSIONS ) )
{
RECT rcWndSize;
GetClientRect( (HWND)m_kWindow.m_hWnd, &rcWndSize );
m_kWindow.m_kResolution.m_uiWidth = rcWndSize.right - rcWndSize.left;
m_kWindow.m_kResolution.m_uiHeight = rcWndSize.bottom - rcWndSize.top;
}
#elif __APPLE__
m_kWindow.m_pWindow = rkWndData.m_pWindow;
#elif POSIX
if( !( m_kWindow.m_pDisplay = rkWndData.m_pDisplay ) )
{
//Ugly solution!
if( !( m_kWindow.m_pDisplay = XOpenDisplay( 0 ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to open display" << endl;
return false;
}
}
m_kWindow.m_Window = rkWndData.m_Window;
#endif
}
//Initialize window
neolog << LogLevel( INFO ) << "Opening render device" << endl;
if( !m_pkFrameBufferTarget )
m_pkFrameBufferTarget = new FrameBufferRenderTarget( this );
#ifdef WIN32
m_pkFrameBufferTarget->m_hDC = GetDC( (HWND)m_kWindow.m_hWnd );
if( !m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
m_kWindow.m_kResolution.m_uiBPP = GetDeviceCaps( m_pkFrameBufferTarget->m_hDC, BITSPIXEL );
if( rkWndData.m_kCaps.IsSet( RenderCaps::STENCILBUFFER ) )
{
if( !m_kWindow.m_kResolution.m_uiStencilBits )
m_kWindow.m_kResolution.m_uiStencilBits = 8;
m_kWindow.m_kCaps.Set( RenderCaps::STENCILBUFFER );
}
else
m_kWindow.m_kResolution.m_uiStencilBits = 0;
// First use normal method to create context to get
PIXELFORMATDESCRIPTOR pfd;
memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
pfd.nVersion = 1;
pfd.dwFlags = PFD_SUPPORT_OPENGL |
PFD_DRAW_TO_WINDOW |
PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = m_kWindow.m_kResolution.m_uiBPP;
pfd.cDepthBits = !m_kWindow.m_kResolution.m_uiDepthBits ? 16 : m_kWindow.m_kResolution.m_uiDepthBits;
pfd.cStencilBits = m_kWindow.m_kResolution.m_uiStencilBits;
pfd.iLayerType = PFD_MAIN_PLANE;
int iPixelFormat = ChoosePixelFormat( m_pkFrameBufferTarget->m_hDC, &pfd );
if( !iPixelFormat )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to find compatible pixel format" << endl;
return false;
}
if( !SetPixelFormat( m_pkFrameBufferTarget->m_hDC, iPixelFormat, &pfd ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to set pixel format" << endl;
return false;
}
m_pkFrameBufferTarget->m_hRC = wglCreateContext( m_pkFrameBufferTarget->m_hDC );
wglMakeCurrent( m_pkFrameBufferTarget->m_hDC, m_pkFrameBufferTarget->m_hRC );
bool bWGLPixelFormat = true;
if( !( fpneowglGetPixelFormatAttribivARB = (fpwglGetPixelFormatAttribivARBProc)GetProcAddress( "wglGetPixelFormatAttribivARB" ) ) )
bWGLPixelFormat = false;
if( !( fpneowglGetPixelFormatAttribfvARB = (fpwglGetPixelFormatAttribfvARBProc)GetProcAddress( "wglGetPixelFormatAttribfvARB" ) ) )
bWGLPixelFormat = false;
if( !( fpneowglChoosePixelFormatARB = (fpwglChoosePixelFormatARBProc)GetProcAddress( "wglChoosePixelFormatARB" ) ) )
bWGLPixelFormat = false;
if( bWGLPixelFormat )
{
wglMakeCurrent( m_pkFrameBufferTarget->m_hDC, 0 );
wglDeleteContext( m_pkFrameBufferTarget->m_hRC );
m_kWindow.m_kCaps.Set( RenderCaps::PIXELFORMAT );
neolog << LogLevel( INFO ) << "Using WGL ARB pixel format methods" << endl;
int aiAccel[3] = { WGL_FULL_ACCELERATION_ARB, WGL_GENERIC_ACCELERATION_ARB, WGL_NO_ACCELERATION_ARB };
int iPass = 0;
iPixelFormat = -1;
for( ; iPass < 3; ++iPass )
{
vector< int > viAttribs;
viAttribs.push_back( WGL_DRAW_TO_WINDOW_ARB ); viAttribs.push_back( TRUE );
viAttribs.push_back( WGL_ACCELERATION_ARB ); viAttribs.push_back( aiAccel[ iPass ] );
//viAttribs.push_back( WGL_SWAP_METHOD_ARB ); viAttribs.push_back( WGL_SWAP_EXCHANGE_ARB );
viAttribs.push_back( WGL_SUPPORT_OPENGL_ARB ); viAttribs.push_back( TRUE );
viAttribs.push_back( WGL_DOUBLE_BUFFER_ARB ); viAttribs.push_back( TRUE );
viAttribs.push_back( WGL_PIXEL_TYPE_ARB ); viAttribs.push_back( WGL_TYPE_RGBA_ARB );
viAttribs.push_back( WGL_COLOR_BITS_ARB ); viAttribs.push_back( m_kWindow.m_kResolution.m_uiBPP );
viAttribs.push_back( WGL_DEPTH_BITS_ARB ); viAttribs.push_back( m_kWindow.m_kResolution.m_uiDepthBits ? m_kWindow.m_kResolution.m_uiDepthBits : 16 );
// Multisample support
if ( m_kWindow.m_uiFsaa > 0 ){
viAttribs.push_back( WGL_SAMPLE_BUFFERS_ARB ); viAttribs.push_back( GL_TRUE );
viAttribs.push_back( WGL_SAMPLES_ARB ) ; viAttribs.push_back( m_kWindow.m_uiFsaa );
}
if( m_kWindow.m_kResolution.m_uiStencilBits )
{ viAttribs.push_back( WGL_STENCIL_BITS_ARB ); viAttribs.push_back( m_kWindow.m_kResolution.m_uiStencilBits ); }
viAttribs.push_back( 0 );
unsigned int uiNumFormats = 0;
int aiFormats[128];
int valid = neowglChoosePixelFormatARB( m_pkFrameBufferTarget->m_hDC, (const int*)&viAttribs.front(), 0, 128, aiFormats, &uiNumFormats );
if( !uiNumFormats )
continue;
neolog << LogLevel( DEBUG ) << "Found [" << uiNumFormats << "] matching pixel formats" << endl;
vector< int > viCheck;
viCheck.push_back( WGL_ACCELERATION_ARB );
viCheck.push_back( WGL_COLOR_BITS_ARB );
viCheck.push_back( WGL_DEPTH_BITS_ARB );
viCheck.push_back( WGL_STENCIL_BITS_ARB );
// Multisample support
if ( m_kWindow.m_uiFsaa > 0 ){
viCheck.push_back( WGL_SAMPLE_BUFFERS_ARB );
viCheck.push_back( WGL_SAMPLES_ARB );
}
viCheck.push_back( 0 );
vector< int > viValues( viCheck.size(), 0 );
unsigned int uiFormat = 0;
for( ; uiFormat < uiNumFormats; ++uiFormat )
{
neowglGetPixelFormatAttribivARB( m_pkFrameBufferTarget->m_hDC, aiFormats[ uiFormat ], 0, viCheck.size() - 1, &viCheck.front(), &viValues.front() );
if( ( viValues[0] == aiAccel[ iPass ] ) &&
( viValues[1] == m_kWindow.m_kResolution.m_uiBPP ) &&
( viValues[2] >= (int)m_kWindow.m_kResolution.m_uiDepthBits ) &&
( viValues[3] >= (int)m_kWindow.m_kResolution.m_uiStencilBits ))
{
// Multisample support
if ( m_kWindow.m_uiFsaa > 0 && ( viValues[4] > 0 ) && ( viValues[5] >= m_kWindow.m_uiFsaa ))
break;
else if ( m_kWindow.m_uiFsaa == 0)
break;
}
}
if( uiFormat >= uiNumFormats )
{
neolog << LogLevel( WARNING ) << "*** None of reported pixelformats match" << endl;
continue;
}
iPixelFormat = aiFormats[ uiFormat ];
if( iPass == 0 )
neolog << LogLevel( INFO ) << "[*] Full acceleration" << endl;
else if( iPass == 1 )
neolog << LogLevel( WARNING ) << "[*] Generic acceleration" << endl;
else if( iPass == 2 )
neolog << LogLevel( WARNING ) << "[*] No acceleration" << endl;
break;
}
if( iPass == 3 )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: unable to find matching pixelformat" << endl;
return false;
}
SetPixelFormat( m_pkFrameBufferTarget->m_hDC, iPixelFormat, 0 );
PIXELFORMATDESCRIPTOR pfd;
memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
DescribePixelFormat( m_pkFrameBufferTarget->m_hDC, iPixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &pfd );
m_pkFrameBufferTarget->m_hRC = wglCreateContext( m_pkFrameBufferTarget->m_hDC );
}
else
{
memset( &pfd, 0, sizeof( PIXELFORMATDESCRIPTOR ) );
pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR );
pfd.nVersion = 1;
DescribePixelFormat( m_pkFrameBufferTarget->m_hDC, iPixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &pfd );
if( pfd.dwFlags & PFD_GENERIC_ACCELERATED )
{
neolog << LogLevel( INFO ) << "[*] Accelerated pixel format" << endl;
m_kWindow.m_kCaps.Set( RenderCaps::HARDWAREACCELERATED );
}
else if( pfd.dwFlags & PFD_GENERIC_FORMAT )
neolog << LogLevel( INFO ) << "[*] GDI software pixel format" << endl;
else
{
neolog << LogLevel( INFO ) << "[*] Accelerated pixel format (noflags)" << endl;
m_kWindow.m_kCaps.Set( RenderCaps::HARDWAREACCELERATED );
}
}
if( pfd.dwFlags & PFD_DOUBLEBUFFER )
{
neolog << LogLevel( INFO ) << "[*] Doublebuffered" << endl;
m_kWindow.m_kCaps.Set( RenderCaps::DOUBLEBUFFER );
}
else
neolog << LogLevel( INFO ) << "[*] Singlebuffered" << endl;
m_kWindow.m_kResolution.m_uiDepthBits = pfd.cDepthBits;
m_kWindow.m_kResolution.m_uiStencilBits = pfd.cStencilBits;
neolog << LogLevel( INFO ) << "[" << m_kWindow.m_kResolution.m_uiDepthBits << "] depth bits" << endl;
if( m_kWindow.m_kResolution.m_uiStencilBits )
{
neolog << LogLevel( INFO ) << "[" << m_kWindow.m_kResolution.m_uiStencilBits << "] stencil bits" << endl;
m_kWindow.m_kCaps.Set( RenderCaps::STENCILBUFFER );
}
else
{
if( m_kWindow.m_kCaps.IsSet( RenderCaps::STENCILBUFFER ) )
neolog << LogLevel( WARNING ) << "*** Stencil buffer requested, not got" << endl;
m_kWindow.m_kCaps.Reset( RenderCaps::STENCILBUFFER );
}
ShowWindow( (HWND)m_kWindow.m_hWnd, SW_NORMAL );
#elif __APPLE__
if( !m_kWindow.m_kResolution.m_uiDepthBits )
m_kWindow.m_kResolution.m_uiDepthBits = 16;
if( !m_kWindow.m_kCaps.IsSet( RenderCaps::FULLSCREEN ) )
{
GLint attrib[] =
{
AGL_RGBA,
AGL_DOUBLEBUFFER,
AGL_DEPTH_SIZE, m_kWindow.m_kResolution.m_uiDepthBits,
AGL_NONE
};
if( !( m_pkFrameBufferTarget->m_aglPixelFormat = aglChoosePixelFormat( NULL, 0, attrib ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to find compatible pixel format" << endl;
return false;
}
if( !( m_pkFrameBufferTarget->m_aglContext = aglCreateContext( m_pkFrameBufferTarget->m_aglPixelFormat, 0 ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to create context" << endl;
return false;
}
}
else
{
CGDirectDisplayID mainDisplay = CGMainDisplayID();
GDHandle gdhDisplay;
OSErr err;
CGDisplayCapture( mainDisplay );
CFDictionaryRef refDisplayMode = CGDisplayBestModeForParameters( mainDisplay, m_kWindow.m_kResolution.m_uiDepthBits, m_kWindow.m_kResolution.m_uiWidth, m_kWindow.m_kResolution.m_uiHeight, NULL );
CGDisplaySwitchToMode( mainDisplay, refDisplayMode );
GLint attrib[] =
{
AGL_RGBA,
AGL_NO_RECOVERY,
AGL_FULLSCREEN,
AGL_DOUBLEBUFFER,
AGL_DEPTH_SIZE, m_kWindow.m_kResolution.m_uiDepthBits,
AGL_NONE
};
if( ( err = DMGetGDeviceByDisplayID( (DisplayIDType)mainDisplay, &gdhDisplay, false ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: DMGetGDeviceByDisplayID error:" << err << endl;
return false;
}
if( !( m_pkFrameBufferTarget->m_aglPixelFormat = aglChoosePixelFormat( &gdhDisplay, 1, attrib ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to find compatible pixel format" << endl;
return false;
}
if( !( m_pkFrameBufferTarget->m_aglContext = aglCreateContext( m_pkFrameBufferTarget->m_aglPixelFormat, NULL ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to create context" << endl;
return false;
}
if( !aglSetFullScreen( m_pkFrameBufferTarget->m_aglContext, m_kWindow.m_kResolution.m_uiWidth, m_kWindow.m_kResolution.m_uiHeight, 0, 0 ) )
{
err = aglGetError();
neolog << LogLevel( ERROR ) << "*** Unable to open device: Unable to enter fullscreen mode: " << err << endl;
return false;
}
m_kWindow.m_pWindow = NULL;
}
aglDestroyPixelFormat( m_pkFrameBufferTarget->m_aglPixelFormat );
m_pkFrameBufferTarget->m_aglPixelFormat = 0;
m_kWindow.m_kCaps.Set( RenderCaps::DOUBLEBUFFER );
#elif POSIX
XVisualInfo *pVisualInfo = GetXVisual( (Display*)m_kWindow.m_pDisplay, &rkWndData.m_kCaps, &m_kWindow.m_kResolution );
if( !pVisualInfo )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to get X visual" << endl;
return false;
}
int iValue = 0;
int aiRGBA[4];
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_DOUBLEBUFFER, &iValue );
if( iValue != True )
neolog << LogLevel( INFO ) << "[*] Singlebuffered" << endl;
else
{
m_kWindow.m_kCaps.Set( RenderCaps::DOUBLEBUFFER );
neolog << LogLevel( INFO ) << "[*] Doublebuffered" << endl;
}
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_RED_SIZE, &aiRGBA[0] );
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_GREEN_SIZE, &aiRGBA[1] );
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_BLUE_SIZE, &aiRGBA[2] );
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_ALPHA_SIZE, &aiRGBA[3] );
neolog << LogLevel( DEBUG ) << "[*] " << aiRGBA[0] << aiRGBA[1] << aiRGBA[2] << aiRGBA[3] << " RGBA bits" << endl;
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_DEPTH_SIZE, &iValue );
neolog << LogLevel( DEBUG ) << "[*] " << iValue << " depth bits" << endl;
if( rkWndData.m_kCaps.IsSet( RenderCaps::STENCILBUFFER ) )
{
iValue = 0;
glXGetConfig( (Display*)m_kWindow.m_pDisplay, pVisualInfo, GLX_STENCIL_SIZE, &iValue );
if( iValue > 0 )
{
neolog << LogLevel( DEBUG ) << "[*] " << iValue << " stencil bits" << endl;
m_kWindow.m_kCaps.Set( RenderCaps::STENCILBUFFER );
}
else
neolog << LogLevel( WARNING ) << "*** Stencil buffer requested, not supported" << endl;
}
if( !( m_pkFrameBufferTarget->m_glxContext = glXCreateContext( (Display*)m_kWindow.m_pDisplay, pVisualInfo, 0, True ) ) )
{
neolog << LogLevel( ERROR ) << "*** Unable to open device: Failed to create context" << endl;
return false;
}
#endif
return Initialize( &rkWndData.m_kCaps );
}
};
See more files for this project here