X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Ffg_main.c;h=fb3d9db15ebdbf349c0a665543c33d2ed8e05601;hb=2985bdd9bc82503cc3fab6b6eb60f4cce59c266c;hp=d2108e7ee6dae53afbbdc4e075a844193b86163b;hpb=8d4c37c07da62376ba4d9d39466f243e0e327300;p=freeglut diff --git a/src/fg_main.c b/src/fg_main.c index d2108e7..fb3d9db 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 */ @@ -261,7 +236,7 @@ static void fghCheckTimers( void ) SFG_Timer *timer = fgState.Timers.First; if( timer->TriggerTime > checkTime ) - /* XXX: are timers always sorted by triggerTime? If not, this and fghNextTimer are wrong */ + /* Timers are sorted by triggerTime */ break; fgListRemove( &fgState.Timers, &timer->Node ); @@ -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; } @@ -388,12 +362,13 @@ static int fghHavePendingRedisplays (void) */ static fg_time_t fghNextTimer( void ) { - fg_time_t currentTime = fgElapsedTime(); - SFG_Timer *timer = fgState.Timers.First; + fg_time_t currentTime; + SFG_Timer *timer = fgState.Timers.First; /* timers are sorted by trigger time, so only have to check the first */ if( !timer ) return INT_MAX; + currentTime = fgElapsedTime(); if( timer->TriggerTime < currentTime ) return 0; else @@ -404,7 +379,7 @@ static void fghSleepForEvents( void ) { fg_time_t msec; - if( fghHavePendingRedisplays( ) ) + if( fghHavePendingWork( ) ) return; msec = fghNextTimer( ); @@ -417,6 +392,54 @@ 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 ); + } +} + + /* -- INTERFACE FUNCTIONS -------------------------------------------------- */ /* @@ -432,12 +455,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( ); }