Ignore:
Timestamp:
May 1, 2009, 5:38:50 AM (11 years ago)
Author:
gb
Message:

Try to run the GLUT event loop on the main thread, just in case some
future OSX release insists on that.

Don't try to start the GLUT event loop at all if on OSX and we're already
a GUI application; error in that case.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/examples/opengl-ffi.lisp

    r9139 r11990  
    2323    (open-shared-library lib))
    2424  #+darwin-target
    25   (open-shared-library "GLUT.framework/GLUT")
     25  (let* ((s (make-semaphore)))
     26    (process-interrupt ccl::*initial-process*
     27                       (lambda ()
     28                         (open-shared-library "GLUT.framework/GLUT")
     29                         (signal-semaphore s)))
     30    (wait-on-semaphore s))
    2631  )
    2732
     
    3136(let ((glut-initialized-p nil))
    3237  (defun initialize-glut ()
    33     (let ((command-line-strings (list "openmcl")))
     38    (let ((command-line-strings (list "ccl")))
    3439      (when (not glut-initialized-p)
    3540        (ccl::with-string-vector (argv command-line-strings)
     
    98103  (#_glutDisplayFunc display-cb)
    99104  (myinit)
    100 ; It appears that glut provides no mechanism for doing the event loop
    101 ; yourself -- if you want to do that, you should use some other set of
    102 ; libraries and make your own GUI toolkit.
     105
     106  ;; It appears that glut provides no mechanism for doing the event loop
     107  ;; yourself -- if you want to do that, you should use some other set of
     108  ;; libraries and make your own GUI toolkit.
    103109 
    104   (#_glutMainLoop) ; this never returns and interferes w/scheduling
     110  (#_glutMainLoop) ; this never returns
    105111  )
    106112
    107113
    108114;;; With native threads, #_glutMainLoop doesn't necessarily interfere
    109 ;;; with scheduling: we can just run all of the OpenGL code in a separate
    110 ;;; thread (which'll probably spend most of its time blocked in GLUT's
    111 ;;; event loop.)  On OSX, we need to use an undocumented API or two
    112 ;;; to ensure that the thread we're creating is seen as the "main"
    113 ;;; event handling thread (that's what the code that sets the current
    114 ;;; thread's CFRunLoop to the main CFRunLoop does.)
    115 #+OpenMCL-native-threads
    116 (ccl:process-run-function
    117  "OpenGL main thread"
    118  #'(lambda ()
    119      #+darwin-target
    120      (progn
    121        ;;; In OSX, a "run loop" is a data structure that
    122        ;;; describes how event-handling code should block
    123        ;;; for events, timers, and other event sources.
    124        ;;; Ensure that this thread has a "current run loop".
    125        ;;; (Under some circumstances, there may not yet be
    126        ;;; a "main" run loop; setting the "current" run loop
    127        ;;; ensures that a main run loop exists.)
    128        (ccl::external-call "_CFRunLoopGetCurrent" :address)
    129        ;;; Make the current thread's run loop be the "main" one;
    130        ;;; only the main run loop can interact with the window
    131        ;;; server.
    132        (ccl::external-call
    133         "__CFRunLoopSetCurrent"
    134         :address (ccl::external-call "_CFRunLoopGetMain" :address))
     115;;; with scheduling: we can just run all of the OpenGL code in a
     116;;; separate thread (which'll probably spend most of its time blocked
     117;;; in GLUT's event loop.)  On OSX (especially) it may work best to
     118;;; force the GLUT event loop to run on the main thread, which
     119;;; ordinarily does period "housekeeping" tasks.  Start another thread
     120;;; to do those tasks, and force the initial/main thread to run the
     121;;; GLUT event loop.
     122;;;
     123
     124;;; Try to detect cases where we're already running some sort of event
     125;;; loop on OSX.  There are other ways to lose, of course.
     126
     127#+darwin-target
     128(progn
     129  (eval-when (:compile-toplevel :execute)
     130    (use-interface-dir :cocoa))
     131  ;; If the current (window system) process is visible (has a UI),
     132  ;; we can't possibly win.
     133  (rlet ((psn #>ProcessSerialNumber))
     134    (and (eql 0 (#_GetCurrentProcess psn))
     135         (not (eql #$false (#_IsProcessVisible psn)))
     136         (error "This is a GLUT example; it can't possibly work ~
     137                 in a GUI environment."))))
     138(progn
     139  (ccl:process-run-function
     140   "housekeeping"
     141   #'ccl::housekeeping-loop)
     142  (ccl:process-interrupt
     143   ccl::*initial-process*
     144   (lambda ()
     145     ;; CCL::%SET-TOPLEVEL is sort of like PROCESS-PRESET for the
     146     ;; initial process; CCL::TOPLEVEL is sort of like PROCESS-RESET
     147     ;; for that process.
     148     (ccl::%set-toplevel
     149      (lambda ()
    135150       ;;; Set the OSX Window Server's notion of the name of the
    136151       ;;; current process.
     
    138153         (#_GetCurrentProcess psn)
    139154         (with-cstrs ((name "simple OpenGL example"))
    140            (ccl::external-call "_CPSSetProcessName" :address psn :address name :void))))
    141      (main)))
     155           (ccl::external-call "_CPSSetProcessName" :address psn :address name :void)))
     156       (ccl::%set-toplevel nil)
     157       (main)))
     158     (ccl::toplevel))))
    142159
    143 ; (main)
    144160
Note: See TracChangeset for help on using the changeset viewer.