X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_main.c;h=3b32f064aa470108a9b17ce9aa71368823d320bc;hb=c2de6d3474dc0c697fa0d5c9fd84988896a077ef;hp=39fecd484aa26da57e384042ca94a4a6e07a650e;hpb=edfc70126a7ad6f62ec86ad7f11b734a10133911;p=freeglut diff --git a/src/fg_main.c b/src/fg_main.c index 39fecd4..3b32f06 100644 --- a/src/fg_main.c +++ b/src/fg_main.c @@ -60,7 +60,9 @@ extern void fgPlatformSleepForEvents( fg_time_t msec ); extern void fgPlatformProcessSingleEvent ( void ); extern void fgPlatformMainLoopPreliminaryWork ( void ); - +extern void fgPlatformInitWork(SFG_Window* window); +extern void fgPlatformPosResZordWork(SFG_Window* window, unsigned int workMask); +extern void fgPlatformVisibilityWork(SFG_Window* window); /* -- PRIVATE FUNCTIONS ---------------------------------------------------- */ @@ -92,7 +94,7 @@ void fghOnReshapeNotify(SFG_Window *window, int width, int height, GLboolean for * window. * DN: Hmm.. the above sounds like a concern only in single buffered mode... */ - glutPostRedisplay( ); + window->State.WorkMask |= GLUT_DISPLAY_WORK; if( window->IsMenu ) fgSetWindow( saved_window ); } @@ -179,33 +181,6 @@ static void fghProcessWork( void ) fgEnumWindows( fghcbProcessWork, &enumerator ); } - -static void fghcbDisplayWindow( SFG_Window *window, - SFG_Enumerator *enumerator ) -{ - if( window->State.Redisplay && - window->State.Visible ) - { - window->State.Redisplay = GL_FALSE; - fghRedrawWindow ( window ); - } - - fgEnumSubWindows( window, fghcbDisplayWindow, enumerator ); -} - -/* - * Make all windows perform a display call - */ -static void fghDisplayAll( void ) -{ - SFG_Enumerator enumerator; - - enumerator.found = GL_FALSE; - enumerator.data = NULL; - - fgEnumWindows( fghcbDisplayWindow, &enumerator ); -} - /* * Window enumerator callback to check for the joystick polling code */ @@ -357,29 +332,28 @@ void fgWarning( const char *fmt, ... ) /* - * Indicates whether a redisplay is pending for ANY window. + * Indicates whether work is pending for ANY window. * * The current mechanism is to walk all of the windows and ask if - * a redisplay is pending. We have a short-circuit early - * return if we find any. + * work is pending. We have a short-circuit early return if we find any. */ -static void fghHavePendingRedisplaysCallback( SFG_Window* w, SFG_Enumerator* e) +static void fghHavePendingWorkCallback( SFG_Window* w, SFG_Enumerator* e) { - if( w->State.Redisplay && w->State.Visible ) + if( w->State.WorkMask ) { e->found = GL_TRUE; e->data = w; return; } - fgEnumSubWindows( w, fghHavePendingRedisplaysCallback, e ); + fgEnumSubWindows( w, fghHavePendingWorkCallback, e ); } -static int fghHavePendingRedisplays (void) +static int fghHavePendingWork (void) { SFG_Enumerator enumerator; enumerator.found = GL_FALSE; enumerator.data = NULL; - fgEnumWindows( fghHavePendingRedisplaysCallback, &enumerator ); + fgEnumWindows( fghHavePendingWorkCallback, &enumerator ); return !!enumerator.data; } @@ -405,7 +379,7 @@ static void fghSleepForEvents( void ) { fg_time_t msec; - if( fghHavePendingRedisplays( ) ) + if( fghHavePendingWork( ) ) return; msec = fghNextTimer( ); @@ -418,6 +392,57 @@ static void fghSleepForEvents( void ) } +/* Step through the work list */ +void fgPlatformProcessWork(SFG_Window *window) +{ + unsigned int workMask = window->State.WorkMask; + /* Now clear it so that any callback generated by the actions below can set work again */ + window->State.WorkMask = 0; + + if (workMask&~GLUT_DISPLAY_WORK) /* Display work is the common case, skip all the below at once */ + { + if (workMask & GLUT_INIT_WORK) + { + /* This is before the first display callback: if needed for the platform, + * call a few callbacks to inform user of window size, position, etc + */ + fgPlatformInitWork(window); + + /* Call init context callback */ + INVOKE_WCB( *window, InitContext, ()); + + /* Lastly, check if we have a display callback, error out if not + * This is the right place to do it, as the redisplay will be + * next right after we exit this function, so there is no more + * opportunity for the user to register a callback for this window. + */ + if (!FETCH_WCB(*window, Display)) + fgError ( "ERROR: No display callback registered for window %d\n", window->ID ); + } + + /* On windows we can position, resize and change z order at the same time */ + if (workMask & (GLUT_POSITION_WORK|GLUT_SIZE_WORK|GLUT_ZORDER_WORK|GLUT_FULL_SCREEN_WORK)) + { + fgPlatformPosResZordWork(window,workMask); + } + + if (workMask & GLUT_VISIBILITY_WORK) + { + fgPlatformVisibilityWork(window); + } + } + + if (workMask & GLUT_DISPLAY_WORK) + { + if( window->State.Visible ) + fghRedrawWindow ( window ); + + /* Strip out display work that might have ended up on work list now as some of the above genereates callbacks */ + window->State.WorkMask &= ~GLUT_DISPLAY_WORK; + } +} + + /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* @@ -433,12 +458,9 @@ void FGAPIENTRY glutMainLoopEvent( void ) if (fgState.NumActiveJoysticks>0) /* If zero, don't poll joysticks */ fghCheckJoystickPolls( ); - /* Perform work on the window (position, reshape, etc) */ + /* Perform work on the window (position, reshape, display, etc) */ fghProcessWork( ); - /* Display */ - fghDisplayAll( ); - fgCloseWindows( ); }