Re: FreeGlut and Lush [PATCH INCLUDED]

Leon Bottou <[email protected]>
Newsgroups gmane.lisp.lush.devel
Message-ID <[email protected]>
The attached patch adds the following  glutGet codes.
These provide means to use glutMainLoopEvent()
without having to poll in a busy loop.

glutGet(GLUT_CONNECTION) --- 
   Returns a system dependent integer indicating  
   how to wait for window system events pertaining 
   to the windows managed by freeglut. 
   - Unix: 		returns a file descriptor for function select() 
   - Win32: 	always returns -1 because the message 
	                source is implicit in the windows API.
   - Other: to be defined
 
glutGet(GLUT_IDLE_TIME) --- 
   Returns the expected idle time. 
   The main loop should not wait more 
   than the expected idle time (in milliseconds) 
   before calling glutMainLoopEvent() again. 
   
   Remark1: The main loop must still call glutMainLoopEvent() 
   as soon as there are pending window system events. 
   But it should also call glutMainLoopEvent() within 
   the specified idle time regardless of the presence 
   of pending window system events.  This is used for 
   timers, joysticks, etc... 
  
  Remark2: A return value of 0 indicates that 
  glutMainLoopEvent() has something do 
 
The patch also includes a fix for bug #944577. 

Remark:  
The choice of GLEnum constants for GLUT_CONNECTION 
and GLUT_IDLE_TIME was made almost randomly.  
I could not find a document explaining the policy for 
these choices.


- Leon Bottou
multiloop.patch (text/x-diff, 5.5 KB)
Index: include/GL/freeglut_ext.h
===================================================================
RCS file: /cvsroot/freeglut/freeglut/freeglut/include/GL/freeglut_ext.h,v
retrieving revision 1.14
diff -u -3 -p -r1.14 freeglut_ext.h
--- include/GL/freeglut_ext.h	15 Mar 2004 06:16:47 -0000	1.14
+++ include/GL/freeglut_ext.h	4 May 2004 15:18:55 -0000
@@ -57,6 +57,9 @@
 
 #define  GLUT_RENDERING_CONTEXT             0x01FD
 
+#define  GLUT_CONNECTION                    0x1001
+#define  GLUT_IDLE_TIME                     0x1002
+
 /*
  * Process loop function, see freeglut_main.c
  */
Index: src/freeglut_internal.h
===================================================================
RCS file: /cvsroot/freeglut/freeglut/freeglut/src/freeglut_internal.h,v
retrieving revision 1.44
diff -u -3 -p -r1.44 freeglut_internal.h
--- src/freeglut_internal.h	15 Mar 2004 13:42:20 -0000	1.44
+++ src/freeglut_internal.h	4 May 2004 15:18:55 -0000
@@ -845,6 +845,27 @@ void fgDisplayCursor( void );
 long fgElapsedTime( void );
 
 /*
+ * Expected idle time as per glutGet(GLUT_IDLE_TIME)
+ *
+ * This means that the main loop should not wait more
+ * than the expected idle time (in milliseconds) 
+ * before calling glutMainLoopEvent() again.  
+ *
+ * Remark1: The main loop must still call glutMainLoopEvent() 
+ * as soon as there are pending window system events.
+ * But it should also call glutMainLoopEvent() within
+ * the specified idle time regardless of the presence
+ * of pending window system events.  This is used for
+ * timers, joysticks, etc...
+ *
+ * Remark2: A return value of 0 indicates that
+ * glutMainLoopEvent() has something do
+ * to immediately.  
+ */
+
+long fgIdleTime( void );
+
+/*
  * List functions
  */
 void fgListInit(SFG_List *list);
Index: src/freeglut_main.c
===================================================================
RCS file: /cvsroot/freeglut/freeglut/freeglut/src/freeglut_main.c,v
retrieving revision 1.100
diff -u -3 -p -r1.100 freeglut_main.c
--- src/freeglut_main.c	22 Mar 2004 10:19:25 -0000	1.100
+++ src/freeglut_main.c	4 May 2004 15:18:55 -0000
@@ -444,35 +444,69 @@ static int fgHavePendingRedisplays (void
     fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
     return !!enumerator.data;
 }
+
 /*
- * Returns the number of GLUT ticks (milliseconds) till the next timer event.
+ * Expected idle time as per glutGet(GLUT_IDLE_TIME)
+ *
+ * This means that the main loop should not wait more
+ * than the expected idle time before calling 
+ * glutMainLoopEvent() again.  
+ *
+ * Remark1: The main loop must still call glutMainLoopEvent() 
+ * as soon as there are pending window system events.
+ * But it should also call glutMainLoopEvent() within
+ * the specified idle time regardless of the presence
+ * of pending window system events.  This is used for
+ * timers, joysticks, etc...
+ *
+ * Remark2: A return value of 0 indicates that
+ * glutMainLoopEvent() has something do
+ * to immediately.  
  */
-static long fgNextTimer( void )
+long fgIdleTime( void )
 {
     long ret = INT_MAX;
     SFG_Timer *timer = fgState.Timers.First;
+    
+    /* GUI events */
+#if TARGET_HOST_WIN32 || TARGET_HOST_WINCE
+    MSG stMsg;
+    if ( PeekMessage( &stMsg, NULL, 0, 0, PM_NOREMOVE ) )
+        return 0;
+#elif TARGET_HOST_UNIX_X11
+    if( XPending( fgDisplay.Display ) )
+        return 0;
+#endif
+
+    /* Internal events */
+    if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
+        return 0;
 
+    /* Timers */
     if( timer )
         ret = timer->TriggerTime - fgElapsedTime();
     if( ret < 0 )
         ret = 0;
 
+    /* Joystick */
+    if( fgHaveJoystick( ) )     /* XXX Use GLUT timers for joysticks... */
+        ret = MIN( ret, 10 );   /* XXX Dumb; forces granularity to .01sec */
+    
+    /* Return */
     return ret;
 }
+
+
 /*
  * Does the magic required to relinquish the CPU until something interesting
  * happens.
  */
 static void fgSleepForEvents( void )
 {
-    long msec;
+    long msec = fgIdleTime( );
 
-    if( fgState.IdleCallback || fgHavePendingRedisplays( ) )
-        return;
-
-    msec = fgNextTimer( );
-    if( fgHaveJoystick( ) )     /* XXX Use GLUT timers for joysticks... */
-        msec = MIN( msec, 10 ); /* XXX Dumb; forces granularity to .01sec */
+    if ( msec <= 0 )
+	return;
 
 #if TARGET_HOST_UNIX_X11
     /*
@@ -573,8 +607,11 @@ void FGAPIENTRY glutMainLoopEvent( void 
                     exit( 0 );
                 }
 
-                fgState.ExecState = GLUT_EXEC_STATE_STOP;
-                return;
+                if( fgState.ActionOnWindowClose == GLUT_ACTION_GLUTMAINLOOP_RETURNS )
+		{
+		    fgState.ExecState = GLUT_EXEC_STATE_STOP;
+                    return;
+                }
             }
             break;
 
Index: src/freeglut_state.c
===================================================================
RCS file: /cvsroot/freeglut/freeglut/freeglut/src/freeglut_state.c,v
retrieving revision 1.25
diff -u -3 -p -r1.25 freeglut_state.c
--- src/freeglut_state.c	16 Mar 2004 08:38:28 -0000	1.25
+++ src/freeglut_state.c	4 May 2004 15:18:56 -0000
@@ -463,6 +463,15 @@ int FGAPIENTRY glutGet( GLenum eWhat )
         return fgState.UseCurrentContext ? GLUT_USE_CURRENT_CONTEXT
                                          : GLUT_CREATE_NEW_CONTEXT;
 
+    case GLUT_IDLE_TIME:
+        return fgIdleTime( );
+
+    case GLUT_CONNECTION:
+#if TARGET_HOST_UNIX_X11
+        return ConnectionNumber( fgDisplay.Display );
+#endif      
+        return -1;
+
     default:
         fgWarning( "glutGet(): missing enum handle %i\n", eWhat );
         break;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.