#include <GL/freeglut.h>
#include "freeglut_internal.h"
+#if TARGET_HOST_POSIX_X11
+#include <limits.h> /* LONG_MAX */
+#endif
+
#if defined(_WIN32_WCE)
# include <Aygshell.h>
# ifdef FREEGLUT_LIB_PRAGMAS
ATTRIB_VAL( GLX_ACCUM_ALPHA_SIZE, 1 );
}
- if( fgState.DisplayMode & GLUT_AUX1 )
- ATTRIB_VAL( GLX_AUX_BUFFERS, 1 );
- if( fgState.DisplayMode & GLUT_AUX2 )
- ATTRIB_VAL( GLX_AUX_BUFFERS, 2 );
- if( fgState.DisplayMode & GLUT_AUX3 )
- ATTRIB_VAL( GLX_AUX_BUFFERS, 3 );
- if( fgState.DisplayMode & GLUT_AUX4 )
- ATTRIB_VAL( GLX_AUX_BUFFERS, 4 );
- if ( fgState.DisplayMode & GLUT_MULTISAMPLE )
- {
- ATTRIB_VAL( GLX_SAMPLE_BUFFERS, 1 );
- }
-
+ if ((fgState.DisplayMode & GLUT_AUX)
+ || (fgState.DisplayMode & GLUT_AUX1)
+ || (fgState.DisplayMode & GLUT_AUX2)
+ || (fgState.DisplayMode & GLUT_AUX3)
+ || (fgState.DisplayMode & GLUT_AUX4))
+ {
+ ATTRIB_VAL(GLX_AUX_BUFFERS, fgState.AuxiliaryBufferNumber)
+ }
+
+ if (fgState.DisplayMode & GLUT_MULTISAMPLE)
+ {
+ ATTRIB_VAL(GLX_SAMPLE_BUFFERS, 1)
+ ATTRIB_VAL(GLX_SAMPLES, fgState.SampleNumber)
+ }
/* Push a null at the end of the list */
ATTRIB( None );
return fbconfig;
}
}
-#endif
+#endif /* TARGET_HOST_POSIX_X11 */
/*
* Setup the pixel format for a Win32 window
#define WGL_SAMPLES_ARB 0x2042
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context 1
+#ifdef WGL_WGLEXT_PROTOTYPES
+extern HGLRC WINAPI wglCreateContextAttribsARB (HDC, HGLRC, const int *);
+#endif /* WGL_WGLEXT_PROTOTYPES */
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC, HGLRC hShareContext, const int *attribList);
+
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#endif
+
+
+void fgNewWGLCreateContext( SFG_Window* window )
+{
+ PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetEntensionsStringARB;
+ HGLRC context;
+ int attribs[7];
+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
+ const char * pWglExtString;
+
+ /* If nothing fancy has been required, leave the context as it is */
+ if ( fgState.MajorVersion == 1 && fgState.MinorVersion == 0 && fgState.ContextFlags == 0 )
+ {
+ return;
+ }
+
+ wglMakeCurrent( window->Window.Device,
+ window->Window.Context );
+
+ wglGetEntensionsStringARB=(PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
+ if ( wglGetEntensionsStringARB == NULL )
+ {
+ return;
+ }
+
+ pWglExtString=wglGetEntensionsStringARB(window->Window.Device);
+ if (( pWglExtString == NULL ) || ( strstr(pWglExtString, "WGL_ARB_create_context") == NULL ))
+ {
+ return;
+ }
+
+ /* new context creation */
+ attribs[0] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[1] = fgState.MajorVersion;
+ attribs[2] = WGL_CONTEXT_MINOR_VERSION_ARB;
+ attribs[3] = fgState.MinorVersion;
+ attribs[4] = WGL_CONTEXT_FLAGS_ARB;
+ attribs[5] = ((fgState.ContextFlags & GLUT_DEBUG) ? WGL_CONTEXT_DEBUG_BIT_ARB : 0) |
+ ((fgState.ContextFlags & GLUT_FORWARD_COMPATIBLE) ? WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB : 0);
+ attribs[6] = 0;
+
+ wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress( "wglCreateContextAttribsARB" );
+ if ( wglCreateContextAttribsARB == NULL )
+ {
+ fgError( "wglCreateContextAttribsARB not found" );
+ }
+
+ context = wglCreateContextAttribsARB( window->Window.Device, 0, attribs );
+ if ( context == NULL )
+ {
+ fgError( "Unable to create OpenGL %d.%d context (flags %x)",
+ fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags );
+ }
+
+ wglMakeCurrent( NULL, NULL );
+ wglDeleteContext( window->Window.Context );
+ window->Window.Context = context;
+}
+
+
GLboolean fgSetupPixelFormat( SFG_Window* window, GLboolean checkOnly,
unsigned char layer_type )
{
HWND hWnd;
HDC hDC, hDC_before=wglGetCurrentDC();
WNDCLASS wndCls;
- ATOM atom;
/* create a dummy window */
ZeroMemory(&wndCls, sizeof(wndCls));
- wndCls.lpfnWndProc = DefWindowProc;
- wndCls.hInstance = fgDisplay.Instance;
- wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
- wndCls.lpszClassName = _T("FREEGLUT_dummy");
- atom = RegisterClass( &wndCls );
+ wndCls.lpfnWndProc = DefWindowProc;
+ wndCls.hInstance = fgDisplay.Instance;
+ wndCls.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
+ wndCls.lpszClassName = _T("FREEGLUT_dummy");
+ RegisterClass( &wndCls );
- hWnd=CreateWindow((LPCSTR)atom, _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
+ hWnd=CreateWindow(_T("FREEGLUT_dummy"), _T(""), WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW , 0,0,0,0, 0, 0, fgDisplay.Instance, 0 );
hDC=GetDC(hWnd);
SetPixelFormat( hDC, pixelformat, ppfd );
}
+
+#if TARGET_HOST_POSIX_X11
+
+#ifndef GLX_CONTEXT_MAJOR_VERSION_ARB
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#endif
+
+#ifndef GLX_CONTEXT_MINOR_VERSION_ARB
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#endif
+
+#ifndef GLX_CONTEXT_FLAGS_ARB
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+#endif
+
+#ifndef GLX_CONTEXT_DEBUG_BIT_ARB
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#endif
+
+#ifndef GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+#endif
+
+typedef GLXContext (*CreateContextAttribsProc)(Display *dpy, GLXFBConfig config,
+ GLXContext share_list, Bool direct,
+ const int *attrib_list);
+
+static GLXContext fghCreateNewContext( SFG_Window* window )
+{
+ /* for color model calculation */
+ int menu = ( window->IsMenu && !fgStructure.MenuContext );
+ int index_mode = ( fgState.DisplayMode & GLUT_INDEX );
+
+ /* "classic" context creation */
+ Display *dpy = fgDisplay.Display;
+ GLXFBConfig config = *(window->Window.FBConfig);
+ int render_type = ( !menu && index_mode ) ? GLX_COLOR_INDEX_TYPE : GLX_RGBA_TYPE;
+ GLXContext share_list = NULL;
+ Bool direct = ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT );
+ GLXContext context;
+
+ /* new context creation */
+ int attribs[7];
+ CreateContextAttribsProc createContextAttribs;
+
+ /* If nothing fancy has been required, simply use the old context creation GLX API entry */
+ if ( fgState.MajorVersion == 1 && fgState.MinorVersion == 0 && fgState.ContextFlags == 0)
+ {
+ context = glXCreateNewContext( dpy, config, render_type, share_list, direct );
+ if ( context == NULL ) {
+ fgError( "could not create new OpenGL context" );
+ }
+ return context;
+ }
+
+ /* color index mode is not available anymore with OpenGL 3.0 */
+ if ( render_type == GLX_COLOR_INDEX_TYPE ) {
+ fgWarning( "color index mode is deprecated, using RGBA mode" );
+ }
+
+ attribs[0] = GLX_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[1] = fgState.MajorVersion;
+ attribs[2] = GLX_CONTEXT_MINOR_VERSION_ARB;
+ attribs[3] = fgState.MinorVersion;
+ attribs[4] = GLX_CONTEXT_FLAGS_ARB;
+ attribs[5] = ((fgState.ContextFlags & GLUT_DEBUG) ? GLX_CONTEXT_DEBUG_BIT_ARB : 0) |
+ ((fgState.ContextFlags & GLUT_FORWARD_COMPATIBLE) ? GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB : 0);
+ attribs[6] = 0;
+
+ createContextAttribs = (CreateContextAttribsProc) fghGetProcAddress( "glXCreateContextAttribsARB" );
+ if ( createContextAttribs == NULL ) {
+ fgError( "glXCreateContextAttribsARB not found" );
+ }
+
+ context = createContextAttribs( dpy, config, share_list, direct, attribs );
+ if ( context == NULL ) {
+ fgError( "could not create new OpenGL %d.%d context (flags %x)",
+ fgState.MajorVersion, fgState.MinorVersion, fgState.ContextFlags );
+ }
+ return context;
+}
+#endif
+
+
/*
* Opens a window. Requires a SFG_Window object created and attached
* to the freeglut structure. OpenGL context is created here.
XSizeHints sizeHints;
XWMHints wmHints;
unsigned long mask;
- int renderType; /* GLX_RGBA_TYPE or GLX_COLOR_INDEX_TYPE */
unsigned int current_DisplayMode = fgState.DisplayMode ;
/* Save the display mode if we are creating a menu window */
* or else use the current context if the user has so specified
*/
- /* Set renderType. */
- if( window->IsMenu && ( ! fgStructure.MenuContext ) )
- {
- /* Display mode has been set to GLUT_RGB. */
- renderType = GLX_RGBA_TYPE;
- }
- else if (fgState.DisplayMode & GLUT_INDEX)
- {
- renderType = GLX_COLOR_INDEX_TYPE;
- }
- else
- {
- renderType = GLX_RGBA_TYPE;
- }
-
if( window->IsMenu )
{
/*
{
fgStructure.MenuContext =
(SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) );
- fgStructure.MenuContext->Context = glXCreateNewContext(
- fgDisplay.Display, *(window->Window.FBConfig), renderType,
- NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
- );
+ fgStructure.MenuContext->MContext = fghCreateNewContext( window );
}
/* window->Window.Context = fgStructure.MenuContext->MContext; */
- window->Window.Context = glXCreateContext(
- fgDisplay.Display, window->Window.FBConfig, renderType,
- NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
- );
+ window->Window.Context = fghCreateNewContext( window );
}
else if( fgState.UseCurrentContext )
{
window->Window.Context = glXGetCurrentContext( );
if( ! window->Window.Context )
- window->Window.Context = glXCreateNewContext(
- fgDisplay.Display, window->Window.FBConfig, renderType,
- NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
- );
+ window->Window.Context = fghCreateNewContext( window );
}
else
- window->Window.Context = glXCreateNewContext(
- fgDisplay.Display, window->Window.FBConfig, renderType,
- NULL, ( fgState.DirectContext != GLUT_FORCE_INDIRECT_CONTEXT )
- );
+ window->Window.Context = fghCreateNewContext( window );
#if !defined( __FreeBSD__ ) && !defined( __NetBSD__ )
if( !glXIsDirect( fgDisplay.Display, window->Window.Context ) )
if( fgState.DirectContext == GLUT_FORCE_DIRECT_CONTEXT )
fgError( "Unable to force direct context rendering for window '%s'",
title );
- else if( fgState.DirectContext == GLUT_TRY_DIRECT_CONTEXT )
- fgWarning( "Unable to create direct context rendering for window '%s'\nThis may hurt performance.",
- title );
}
#endif
SetWindowLong ( window->Window.Handle, GWL_STYLE,
WindowStyle & ~(WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX));
}
-//SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
-// SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+/* SetWindowPos(window->Window.Handle, NULL, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); */
#if defined(_WIN32_WCE)
{
#if TARGET_HOST_POSIX_X11
- glXDestroyContext( fgDisplay.Display, window->Window.Context );
- XFree( window->Window.VisualInfo );
+ if( window->Window.Context )
+ glXDestroyContext( fgDisplay.Display, window->Window.Context );
+ XFree( window->Window.FBConfig );
XDestroyWindow( fgDisplay.Display, window->Window.Handle );
- XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
+ /* XFlush( fgDisplay.Display ); */ /* XXX Shouldn't need this */
#elif TARGET_HOST_MS_WINDOWS
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutReshapeWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutReshapeWindow" );
+ if (glutGet(GLUT_FULL_SCREEN))
+ {
+ /* Leave full screen state before resizing. */
+ glutFullScreenToggle();
+ }
+
fgStructure.CurrentWindow->State.NeedToResize = GL_TRUE;
fgStructure.CurrentWindow->State.Width = width ;
fgStructure.CurrentWindow->State.Height = height;
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutPositionWindow" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutPositionWindow" );
+ if (glutGet(GLUT_FULL_SCREEN))
+ {
+ /* Leave full screen state before moving. */
+ glutFullScreenToggle();
+ }
+
#if TARGET_HOST_POSIX_X11
XMoveWindow( fgDisplay.Display, fgStructure.CurrentWindow->Window.Handle,
FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreen" );
FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreen" );
+ if (glutGet(GLUT_FULL_SCREEN))
{
-#if TARGET_HOST_POSIX_X11
- int x, y;
- Window w;
+ /* Leave full screen state before resizing. */
+ glutFullScreenToggle();
+ }
- XMoveResizeWindow(
- fgDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- 0, 0,
- fgDisplay.ScreenWidth,
- fgDisplay.ScreenHeight
- );
+ {
+#if TARGET_HOST_POSIX_X11
- XFlush( fgDisplay.Display ); /* This is needed */
+ Status status; /* Returned by XGetWindowAttributes(), not checked. */
+ XWindowAttributes attributes;
- XTranslateCoordinates(
- fgDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- fgDisplay.RootWindow,
- 0, 0, &x, &y, &w
- );
+ status = XGetWindowAttributes(fgDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ &attributes);
+ /*
+ * The "x" and "y" members of "attributes" are the window's coordinates
+ * relative to its parent, i.e. to the decoration window.
+ */
+ XMoveResizeWindow(fgDisplay.Display,
+ fgStructure.CurrentWindow->Window.Handle,
+ -attributes.x,
+ -attributes.y,
+ fgDisplay.ScreenWidth,
+ fgDisplay.ScreenHeight);
- if (x || y)
- {
- XMoveWindow(
- fgDisplay.Display,
- fgStructure.CurrentWindow->Window.Handle,
- -x, -y
- );
- XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */
- }
#elif TARGET_HOST_MS_WINDOWS && !defined(_WIN32_WCE) /* FIXME: what about WinCE */
RECT rect;
}
/*
+ * Toggle the window's full screen state.
+ */
+void FGAPIENTRY glutFullScreenToggle( void )
+{
+ FREEGLUT_EXIT_IF_NOT_INITIALISED ( "glutFullScreenToggle" );
+ FREEGLUT_EXIT_IF_NO_WINDOW ( "glutFullScreenToggle" );
+
+ {
+#if TARGET_HOST_POSIX_X11
+
+ if (fgDisplay.StateFullScreen != None)
+ {
+ XEvent xevent;
+ long event_mask;
+ int status;
+
+ xevent.type = ClientMessage;
+ xevent.xclient.type = ClientMessage;
+ xevent.xclient.serial = 0;
+ xevent.xclient.send_event = True;
+ xevent.xclient.display = fgDisplay.Display;
+ xevent.xclient.window = fgStructure.CurrentWindow->Window.Handle;
+ xevent.xclient.message_type = fgDisplay.State;
+ xevent.xclient.format = 32;
+ xevent.xclient.data.l[0] = 2; /* _NET_WM_STATE_TOGGLE */
+ xevent.xclient.data.l[1] = fgDisplay.StateFullScreen;
+ xevent.xclient.data.l[2] = 0;
+ xevent.xclient.data.l[3] = 0;
+ xevent.xclient.data.l[4] = 0;
+
+ /*** Don't really understand how event masks work... ***/
+ event_mask = SubstructureRedirectMask | SubstructureNotifyMask;
+
+ status = XSendEvent(fgDisplay.Display,
+ fgDisplay.RootWindow,
+ False,
+ event_mask,
+ &xevent);
+ FREEGLUT_INTERNAL_ERROR_EXIT(status != 0,
+ "XSendEvent failed",
+ "glutFullScreenToggle");
+ }
+ else
+#endif
+ {
+ /*
+ * If the window manager is not Net WM compliant, fall back to legacy
+ * behaviour.
+ */
+ glutFullScreen();
+ }
+ }
+}
+
+/*
* A.Donev: Set and retrieve the window's user data
*/
void* FGAPIENTRY glutGetWindowData( void )