add (figl glu)
[clinton/guile-figl.git] / figl / runtime.scm
index 86022d5..d4515e8 100644 (file)
 
 (define-module (figl runtime)
   #:use-module (system foreign)
-  #:export (current-resolver
-            define-foreign-procedure
+  #:export (define-foreign-procedure
             define-foreign-procedures
             define-foreign-type
-            define-simple-foreign-type))
-
-;;
-;; OpenGL and loading.  What a mess.  So, in the beginning, when
-;; Microsoft added support for OpenGL to Windows, they did so via a
-;; trampoline DLL.  This DLL had a fixed number of entry points, and it
-;; was independent of the driver that the graphics card provided.  It
-;; also provided an extension interface, wglGetProcAddress, which could
-;; return additional GL procedures by name.  Microsoft was unwilling to
-;; extend their trampoline DLL for whatever reason, and so on Windows
-;; you always needed to wglGetProcAddress for almost any OpenGL
-;; function.
-;;
-;; Time passed and GLX and other GL implementations started to want
-;; extensions too.  This let application vendors ship applications that
-;; could take advantage of the capabilities of users's graphics cards
-;; without requiring that they be present.
-;;
-;; There are a couple of differences between WGL and GLX, however.
-;; Chiefly, wglGetProcAddress can only be called once you have a
-;; context, and the resulting function can only be used in that context.
-;; In practice it seems that it can be used also in other contexts that
-;; end up referring to that same driver and GPU.  GLX on the other hand
-;; is context-independent, but presence of a function does not mean that
-;; the corresponding functionality is actually available.  In theory
-;; users have to check for the presence of the GL extension or check the
-;; core GL version, depending on whether the interface is an extension
-;; or in GL core.
-;;
-;; Because of this difference between the GLX and WGL semantics, there
-;; is no core "glGetProcAddress" function.  It's terrible: each
-;; windowing system is responsible for providing their own
-;; function-loader interface.
-;;
-;; Finally, Guile needs to load up at least some interfaces using
-;; dynamic-link / dynamic-pointer in order to be able to talk to the
-;; library at all (and to open a context in the case of Windows), and it
-;; happens that these interfaces also work fine for getting some of the
-;; GL functionality!
-;;
-;; All of this mess really has very little place in the world of free
-;; software, where dynamic linking is entirely sufficient to deal with
-;; this issue, but it is how things have evolved.
-;;
-;; In light of all of this, we need to make some simplifications.
-;;
-;; One is that each low-level function will have just one foreign
-;; function wrapper.  This means that a minority of Windows
-;; configurations won't work.  Oh well.
-;;
-;; Another is that if dynamic-link returns a result, that it is assumed
-;; that glXGetProcAddress (or the equivalent) would return the same
-;; value.  So we can try dynamic-link first, and only dispatch to e.g
-;; glXGetProcAddress if that fails.
-;;
-;; Finally, we assume that all GL symbols may be resolved by
-;; dynamic-pointer by looking in one library, regardless of whether they
-;; come from the lower GL level or from the window-system-specific
-;; level.
-;;
-
-;; FIXME: adapt implementation to match!
-(define (default-resolver name)
-  (dynamic-pointer name (dynamic-link)))
-
-(define current-resolver
-  (make-parameter default-resolver))
-
-(define (resolve name)
-  ((current-resolver) name))
+            define-simple-foreign-type
+            define-enumeration
+            define-bitfield))
 
 (define-syntax foreign-trampoline
-  (lambda (stx)
-    (syntax-case stx (->)
-      ((_ trampoline
-          name (pname ptype) ... -> type)
-       (with-syntax ((sname (symbol->string (syntax->datum #'name))))
-         #'(lambda (pname ...)
-             (let ((ptr (resolve sname)))
-               (set! trampoline
-                     (pointer->procedure (type)
-                                         ptr
-                                         (list (ptype) ...)))
-               (trampoline pname ...))))))))
+  (syntax-rules (->)
+    ((_ trampoline resolve-name (pname ptype) ... -> type)
+     (lambda (pname ...)
+       (set! trampoline
+             (pointer->procedure (type)
+                                 resolve-name
+                                 (list (ptype) ...)))
+       (trampoline pname ...)))))
 
 (define-syntax define-foreign-procedure
   (syntax-rules (->)
     ((define-foreign-procedure (name (pname ptype) ... -> type)
+       resolve-name
        docstring)
      (define name
        (letrec ((trampoline
-                 (foreign-trampoline trampoline
-                                     name (pname ptype) ... -> type))
+                 (foreign-trampoline trampoline resolve-name
+                                     (pname ptype) ... -> type))
                 (name (lambda (pname ...)
                         docstring
                         (let ((pname (ptype #:unwrap pname))
 (define-syntax define-foreign-procedures
   (syntax-rules ()
     ((define-foreign-procedures ((name prototype ...) ...)
+       resolve-name
        docstring)
      (begin
        (define-foreign-procedure (name prototype ...)
+         resolve-name
          docstring)
        ...))))
 
          ((_) ffi-type)
          ((_ #:wrap x) x)
          ((_ #:unwrap x) x))))))
+
+(define-syntax-rule (define-enumeration enumerator (name value) ...)
+  (define-syntax enumerator
+    (lambda (x)
+      (syntax-case x ()
+        ((_)
+         #''(name ...))
+        ((_ enum) (number? (syntax->datum #'enum))
+         #'enum)
+        ((_ enum)
+         (or (assq-ref '((name . value) ...)
+                       (syntax->datum #'enum))
+             (syntax-violation 'enumerator "invalid enumerated value"
+                               #'enum)))))))
+
+(define-syntax-rule (define-bitfield bitfield (name value) ...)
+  (define-syntax bitfield
+    (lambda (x)
+      (syntax-case x ()
+        ((_)
+         #''(name ...))
+        ((_ bit (... ...))
+         #`(logior
+            #,@(map
+                (lambda (bit)
+                  (let ((datum (syntax->datum bit)))
+                    (if (number? datum)
+                        datum
+                        (or (assq-ref '((name . value) ...) datum)
+                            (syntax-violation 'bitfield "invalid bitfield value"
+                                              bit)))))
+                #'(bit (... ...)))))))))