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 ---------------------------------------------------- */
* 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 );
}
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
*/
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 );
/*
- * 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;
}
*/
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
{
fg_time_t msec;
- if( fghHavePendingRedisplays( ) )
+ if( fghHavePendingWork( ) )
return;
msec = fghNextTimer( );
}
+/* 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 -------------------------------------------------- */
/*
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( );
}