From 190a2601431c760659419e5faa568dfab5956581 Mon Sep 17 00:00:00 2001 From: rkrolib Date: Sat, 7 Feb 2004 10:40:59 +0000 Subject: [PATCH] Adds GLUT_OFFSCREEN as a display mode option. This includes: * Recognizing the mode when you call glutCreateWindow(). (Offscreen looks and acts like a top-level window in many ways.) * During the life of the offscreen "window", various window-management functions are modified to respect offscreen status. (Excepting reshaping windows, there is not much useful interpretation for managment of offscreen areas. Reshaping is possibly more work than it's worth to support, and GLUT specs allow us to ignore the request.) * Cleanup for "offscreen" windows is a little different than for regular windows. Windows still don't start up quite ideally. Offscreen windows should probably get a reshape event, but not a display. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@451 7f0cb862-5218-0410-a997-914c9d46530a --- freeglut/freeglut/src/freeglut_internal.h | 4 +- freeglut/freeglut/src/freeglut_window.c | 332 +++++++++++++--------- 2 files changed, 194 insertions(+), 142 deletions(-) diff --git a/freeglut/freeglut/src/freeglut_internal.h b/freeglut/freeglut/src/freeglut_internal.h index a97e029..3d73efc 100644 --- a/freeglut/freeglut/src/freeglut_internal.h +++ b/freeglut/freeglut/src/freeglut_internal.h @@ -341,6 +341,8 @@ struct tagSFG_Context #if TARGET_HOST_UNIX_X11 XVisualInfo* VisualInfo; /* The window's visual information */ + Pixmap Pixmap; /* Used for offscreen rendering */ + //GLXPixmap GLXPixMap; /* Used for offscreen rendering */ #elif TARGET_HOST_WIN32 HDC Device; /* The window's device context */ #endif @@ -370,8 +372,8 @@ struct tagSFG_WindowState int MouseX, MouseY; /* The most recent mouse position */ GLboolean IsGameMode; /* Is this the game mode window? */ - GLboolean NeedToResize; /* Do we need to resize the window? */ + GLboolean IsOffscreen; /* Tags a `window' as on/offscreen. */ }; diff --git a/freeglut/freeglut/src/freeglut_window.c b/freeglut/freeglut/src/freeglut_window.c index 12e6b52..f99b673 100644 --- a/freeglut/freeglut/src/freeglut_window.c +++ b/freeglut/freeglut/src/freeglut_window.c @@ -267,30 +267,30 @@ void fgOpenWindow( SFG_Window* window, const char* title, * XXX With a little thought, we should be able to greatly * XXX simplify this. */ - if ( !window->IsMenu ) - window->Window.VisualInfo = fgChooseVisual(); - else if ( fgStructure.MenuContext ) - window->Window.VisualInfo = fgChooseVisual(); + if( !window->IsMenu ) + window->Window.VisualInfo = fgChooseVisual( ); + else if( fgStructure.MenuContext ) + window->Window.VisualInfo = fgChooseVisual( ); else { unsigned int current_DisplayMode = fgState.DisplayMode ; fgState.DisplayMode = GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH ; - window->Window.VisualInfo = fgChooseVisual(); + window->Window.VisualInfo = fgChooseVisual( ); fgState.DisplayMode = current_DisplayMode ; } - if ( ! window->Window.VisualInfo ) + if( ! window->Window.VisualInfo ) { /* * The "fgChooseVisual" returned a null meaning that the visual * context is not available. * Try a couple of variations to see if they will work. */ - if ( ! ( fgState.DisplayMode & GLUT_DOUBLE ) ) + if( !( fgState.DisplayMode & GLUT_DOUBLE ) ) { fgState.DisplayMode |= GLUT_DOUBLE ; - window->Window.VisualInfo = fgChooseVisual(); - fgState.DisplayMode &= ~GLUT_DOUBLE ; + window->Window.VisualInfo = fgChooseVisual( ); + fgState.DisplayMode &= ~GLUT_DOUBLE; } /* @@ -299,66 +299,95 @@ void fgOpenWindow( SFG_Window* window, const char* title, */ } + /* + * XXX This seems to be abusing an assert() for error-checking. + * XXX It is possible that the visual simply can't be found, + * XXX in which case we should print an error and return a 0 + * XXX for the window id, I think. + */ assert( window->Window.VisualInfo != NULL ); - /* - * XXX HINT: the masks should be updated when adding/removing callbacks. - * XXX This might speed up message processing. Is that true? - * XXX - * XXX A: Not appreciably, but it WILL make it easier to debug. - * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT - * XXX turns off events that it doesn't need and is a whole lot - * XXX more pleasant to trace. (Hint: Think mouse-motion!) - * XXX - * XXX It may make a difference in networked environments or on - * XXX some very slow systems, but I think that that is secondary - * XXX to making debugging easier. - */ - winAttr.event_mask = StructureNotifyMask | SubstructureNotifyMask | - ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | - KeyRelease | VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | - PointerMotionMask | ButtonMotionMask; - winAttr.background_pixmap = None; - winAttr.background_pixel = 0; - winAttr.border_pixel = 0; - - winAttr.colormap = XCreateColormap( - fgDisplay.Display, fgDisplay.RootWindow, - window->Window.VisualInfo->visual, AllocNone - ); - - mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; - - if ( window->IsMenu ) + window->State.IsOffscreen = GL_FALSE; + if( fgState.DisplayMode & GLUT_OFFSCREEN ) { - winAttr.override_redirect = True; - mask |= CWOverrideRedirect; + window->State.IsOffscreen = GL_TRUE; + window->Window.Pixmap = XCreatePixmap( + fgDisplay.Display, fgDisplay.RootWindow, + w, h, + window->Window.VisualInfo->depth + ); + if( False != window->Window.Pixmap ) + { + window->Window.Handle = glXCreateGLXPixmap( + fgDisplay.Display, + window->Window.VisualInfo, + window->Window.Pixmap + ); + if( False == window->Window.Handle ) + XFreePixmap( fgDisplay.Display, window->Window.Pixmap ); + } } + else + { + /* + * XXX HINT: the masks should be updated when adding/removing callbacks. + * XXX This might speed up message processing. Is that true? + * XXX + * XXX A: Not appreciably, but it WILL make it easier to debug. + * XXX Try tracing old GLUT and try tracing freeglut. Old GLUT + * XXX turns off events that it doesn't need and is a whole lot + * XXX more pleasant to trace. (Hint: Think mouse-motion!) + * XXX + * XXX It may make a difference in networked environments or on + * XXX some very slow systems, but I think that that is secondary + * XXX to making debugging easier. + */ + winAttr.event_mask = + StructureNotifyMask | SubstructureNotifyMask | ExposureMask | + ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyRelease | + VisibilityChangeMask | EnterWindowMask | LeaveWindowMask | + PointerMotionMask | ButtonMotionMask; + winAttr.background_pixmap = None; + winAttr.background_pixel = 0; + winAttr.border_pixel = 0; - window->Window.Handle = XCreateWindow( - fgDisplay.Display, - window->Parent == NULL ? fgDisplay.RootWindow : - window->Parent->Window.Handle, - x, y, w, h, 0, - window->Window.VisualInfo->depth, InputOutput, - window->Window.VisualInfo->visual, mask, - &winAttr - ); + winAttr.colormap = XCreateColormap( + fgDisplay.Display, fgDisplay.RootWindow, + window->Window.VisualInfo->visual, AllocNone + ); + mask = CWBackPixmap | CWBorderPixel | CWColormap | CWEventMask; + + if ( window->IsMenu ) + { + winAttr.override_redirect = True; + mask |= CWOverrideRedirect; + } + + window->Window.Handle = XCreateWindow( + fgDisplay.Display, + window->Parent == NULL ? fgDisplay.RootWindow : + window->Parent->Window.Handle, + x, y, w, h, 0, + window->Window.VisualInfo->depth, InputOutput, + window->Window.VisualInfo->visual, mask, + &winAttr + ); + } /* * The GLX context creation, possibly trying the direct context rendering * or else use the current context if the user has so specified */ - if ( window->IsMenu ) + if( window->IsMenu ) { /* * If there isn't already an OpenGL rendering context for menu * windows, make one */ - if ( !fgStructure.MenuContext ) + if( !fgStructure.MenuContext ) { fgStructure.MenuContext = - (SFG_MenuContext *)malloc ( sizeof(SFG_MenuContext) ); + (SFG_MenuContext *)malloc( sizeof(SFG_MenuContext) ); fgStructure.MenuContext->VisualInfo = window->Window.VisualInfo; fgStructure.MenuContext->Context = glXCreateContext( fgDisplay.Display, fgStructure.MenuContext->VisualInfo, @@ -372,15 +401,15 @@ void fgOpenWindow( SFG_Window* window, const char* title, NULL, fgState.ForceDirectContext | fgState.TryDirectContext ); } - else if ( fgState.UseCurrentContext ) + else if( fgState.UseCurrentContext ) { - window->Window.Context = glXGetCurrentContext(); + window->Window.Context = glXGetCurrentContext( ); - if ( ! window->Window.Context ) - window->Window.Context = glXCreateContext( - fgDisplay.Display, window->Window.VisualInfo, - NULL, fgState.ForceDirectContext | fgState.TryDirectContext - ); + if( ! window->Window.Context ) + window->Window.Context = glXCreateContext( + fgDisplay.Display, window->Window.VisualInfo, + NULL, fgState.ForceDirectContext | fgState.TryDirectContext + ); } else window->Window.Context = glXCreateContext( @@ -426,27 +455,31 @@ void fgOpenWindow( SFG_Window* window, const char* title, wmHints.flags = StateHint; wmHints.initial_state = fgState.ForceIconic ? IconicState : NormalState; + if( GL_FALSE == window->State.IsOffscreen ) + { + /* + * Prepare the window and iconified window names... + */ + XStringListToTextProperty( (char **) &title, 1, &textProperty ); - /* - * Prepare the window and iconified window names... - */ - XStringListToTextProperty( (char **) &title, 1, &textProperty ); - - XSetWMProperties( - fgDisplay.Display, - window->Window.Handle, - &textProperty, - &textProperty, - 0, - 0, - &sizeHints, - &wmHints, - NULL - ); - XSetWMProtocols( fgDisplay.Display, window->Window.Handle, - &fgDisplay.DeleteWindow, 1 ); - XMapWindow( fgDisplay.Display, window->Window.Handle ); - + XSetWMProperties( + fgDisplay.Display, + window->Window.Handle, + &textProperty, + &textProperty, + 0, + 0, + &sizeHints, + &wmHints, + NULL + ); + + XSetWMProtocols( fgDisplay.Display, window->Window.Handle, + &fgDisplay.DeleteWindow, 1 ); + + XMapWindow( fgDisplay.Display, window->Window.Handle ); + } + #elif TARGET_HOST_WIN32 WNDCLASS wc; @@ -552,7 +585,13 @@ void fgCloseWindow( SFG_Window* window ) #if TARGET_HOST_UNIX_X11 glXDestroyContext( fgDisplay.Display, window->Window.Context ); - XDestroyWindow( fgDisplay.Display, window->Window.Handle ); + if( GL_FALSE == window->State.IsOffscreen ) + XDestroyWindow( fgDisplay.Display, window->Window.Handle ); + else + { + glXDestroyGLXPixmap( fgDisplay.Display, window->Window.Handle ); + XFreePixmap( fgDisplay.Display, window->Window.Pixmap ); + } XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ #elif TARGET_HOST_WIN32 @@ -671,17 +710,19 @@ void FGAPIENTRY glutShowWindow( void ) freeglut_assert_ready; freeglut_assert_window; + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); - XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ + XMapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); + XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ #elif TARGET_HOST_WIN32 - ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW ); + ShowWindow( fgStructure.Window->Window.Handle, SW_SHOW ); #endif - + } fgStructure.Window->State.Redisplay = GL_TRUE; } @@ -693,21 +734,25 @@ void FGAPIENTRY glutHideWindow( void ) freeglut_assert_ready; freeglut_assert_window; + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - if( fgStructure.Window->Parent == NULL ) - XWithdrawWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, - fgDisplay.Screen ); - else - XUnmapWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); - XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ + if( fgStructure.Window->Parent == NULL ) + XWithdrawWindow( fgDisplay.Display, + fgStructure.Window->Window.Handle, + fgDisplay.Screen ); + else + XUnmapWindow( fgDisplay.Display, + fgStructure.Window->Window.Handle ); + XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ #elif TARGET_HOST_WIN32 - ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE ); + ShowWindow( fgStructure.Window->Window.Handle, SW_HIDE ); #endif - + } fgStructure.Window->State.Redisplay = GL_FALSE; } @@ -720,19 +765,20 @@ void FGAPIENTRY glutIconifyWindow( void ) freeglut_assert_window; fgStructure.Window->State.Visible = GL_FALSE; - + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, - fgDisplay.Screen ); - XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ + XIconifyWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, + fgDisplay.Screen ); + XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ #elif TARGET_HOST_WIN32 - ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE ); + ShowWindow( fgStructure.Window->Window.Handle, SW_MINIMIZE ); #endif - + } fgStructure.Window->State.Redisplay = GL_FALSE; } @@ -743,12 +789,11 @@ void FGAPIENTRY glutSetWindowTitle( const char* title ) { freeglut_assert_ready; freeglut_assert_window; - if( fgStructure.Window->Parent != NULL ) - return; - + if( ! fgStructure.Window->Parent && + ( GL_FALSE == fgStructure.Window->State.IsOffscreen ) ) + { #if TARGET_HOST_UNIX_X11 - { XTextProperty text; text.value = (unsigned char *) title; @@ -763,14 +808,13 @@ void FGAPIENTRY glutSetWindowTitle( const char* title ) ); XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ - } #elif TARGET_HOST_WIN32 - SetWindowText( fgStructure.Window->Window.Handle, title ); + SetWindowText( fgStructure.Window->Window.Handle, title ); #endif - + } } /* @@ -781,12 +825,11 @@ void FGAPIENTRY glutSetIconTitle( const char* title ) freeglut_assert_ready; freeglut_assert_window; - if( fgStructure.Window->Parent != NULL ) - return; - + if( ! fgStructure.Window->Parent && + GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - { XTextProperty text; text.value = (unsigned char *) title; @@ -801,14 +844,13 @@ void FGAPIENTRY glutSetIconTitle( const char* title ) ); XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ - } #elif TARGET_HOST_WIN32 - SetWindowText( fgStructure.Window->Window.Handle, title ); + SetWindowText( fgStructure.Window->Window.Handle, title ); #endif - + } } /* @@ -819,9 +861,13 @@ void FGAPIENTRY glutReshapeWindow( int width, int height ) freeglut_assert_ready; freeglut_assert_window; - fgStructure.Window->State.NeedToResize = GL_TRUE; - fgStructure.Window->State.Width = width ; - fgStructure.Window->State.Height = height; + /* XXX Could delete/create/set-window-id for offscreen. */ + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { + fgStructure.Window->State.NeedToResize = GL_TRUE; + fgStructure.Window->State.Width = width ; + fgStructure.Window->State.Height = height; + } } /* @@ -832,14 +878,16 @@ void FGAPIENTRY glutPositionWindow( int x, int y ) freeglut_assert_ready; freeglut_assert_window; + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, x, y ); - XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ + XMoveWindow( fgDisplay.Display, fgStructure.Window->Window.Handle, + x, y ); + XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ #elif TARGET_HOST_WIN32 - { RECT winRect; GetWindowRect( fgStructure.Window->Window.Handle, &winRect ); @@ -851,10 +899,9 @@ void FGAPIENTRY glutPositionWindow( int x, int y ) winRect.bottom - winRect.top, TRUE ); - } #endif - + } } /* @@ -865,21 +912,23 @@ void FGAPIENTRY glutPushWindow( void ) freeglut_assert_ready; freeglut_assert_window; + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); + XLowerWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); #elif TARGET_HOST_WIN32 - SetWindowPos( - fgStructure.Window->Window.Handle, - HWND_BOTTOM, - 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE - ); + SetWindowPos( + fgStructure.Window->Window.Handle, + HWND_BOTTOM, + 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE + ); #endif - + } } /* @@ -890,21 +939,23 @@ void FGAPIENTRY glutPopWindow( void ) freeglut_assert_ready; freeglut_assert_window; + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) + { #if TARGET_HOST_UNIX_X11 - XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); + XRaiseWindow( fgDisplay.Display, fgStructure.Window->Window.Handle ); #elif TARGET_HOST_WIN32 - SetWindowPos( - fgStructure.Window->Window.Handle, - HWND_TOP, - 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE - ); + SetWindowPos( + fgStructure.Window->Window.Handle, + HWND_TOP, + 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE + ); #endif - + } } /* @@ -915,8 +966,9 @@ void FGAPIENTRY glutFullScreen( void ) freeglut_assert_ready; freeglut_assert_window; -#if TARGET_HOST_UNIX_X11 + if( GL_FALSE == fgStructure.Window->State.IsOffscreen ) { +#if TARGET_HOST_UNIX_X11 int x, y; Window w; @@ -946,9 +998,7 @@ void FGAPIENTRY glutFullScreen( void ) ); XFlush( fgDisplay.Display ); /* XXX Shouldn't need this */ } - } #elif TARGET_HOST_WIN32 - { RECT rect; /* For fullscreen mode, force the top-left corner to 0,0 @@ -980,8 +1030,8 @@ void FGAPIENTRY glutFullScreen( void ) SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER ); - } #endif + } } /* @@ -994,7 +1044,7 @@ void* FGAPIENTRY glutGetWindowData( void ) void FGAPIENTRY glutSetWindowData(void* data) { - fgStructure.Window->UserData=data; + fgStructure.Window->UserData = data; } /*** END OF FILE ***/