fix the resolver mess, and add glut to the build
[clinton/guile-figl.git] / figl / gl / runtime.scm
CommitLineData
25072f02
AW
1;;; figl
2;;; Copyright (C) 2013 Andy Wingo <wingo@pobox.com>
3;;;
4;;; Figl is free software: you can redistribute it and/or modify it
5;;; under the terms of the GNU Lesser General Public License as
6;;; published by the Free Software Foundation, either version 3 of the
7;;; License, or (at your option) any later version.
8;;;
9;;; Figl is distributed in the hope that it will be useful, but WITHOUT
10;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12;;; Public License for more details.
13;;;
14;;; You should have received a copy of the GNU Lesser General Public
15;;; License along with this program. If not, see
16;;; <http://www.gnu.org/licenses/>.
17
18;;; Commentary:
19;;
20;; figl is the Foreign Interface to GL.
21;;
22;;; Code:
23
24(define-module (figl gl runtime)
25 #:use-module (system foreign)
26 #:use-module (figl runtime)
27 #:export (current-gl-resolver
28 current-gl-get-dynamic-object
29 define-gl-procedure
30 define-gl-procedures))
31
32(module-use! (module-public-interface (current-module))
33 (resolve-interface '(figl runtime)))
34
35;;
36;; OpenGL and loading. What a mess. So, in the beginning, when
37;; Microsoft added support for OpenGL to Windows, they did so via a
38;; trampoline DLL. This DLL had a fixed number of entry points, and it
39;; was independent of the driver that the graphics card provided. It
40;; also provided an extension interface, wglGetProcAddress, which could
41;; return additional GL procedures by name. Microsoft was unwilling to
42;; extend their trampoline DLL for whatever reason, and so on Windows
43;; you always needed to wglGetProcAddress for almost any OpenGL
44;; function.
45;;
46;; Time passed and GLX and other GL implementations started to want
47;; extensions too. This let application vendors ship applications that
48;; could take advantage of the capabilities of users's graphics cards
49;; without requiring that they be present.
50;;
51;; There are a couple of differences between WGL and GLX, however.
52;; Chiefly, wglGetProcAddress can only be called once you have a
53;; context, and the resulting function can only be used in that context.
54;; In practice it seems that it can be used also in other contexts that
55;; end up referring to that same driver and GPU. GLX on the other hand
56;; is context-independent, but presence of a function does not mean that
57;; the corresponding functionality is actually available. In theory
58;; users have to check for the presence of the GL extension or check the
59;; core GL version, depending on whether the interface is an extension
60;; or in GL core.
61;;
62;; Because of this difference between the GLX and WGL semantics, there
63;; is no core "glGetProcAddress" function. It's terrible: each
64;; windowing system is responsible for providing their own
65;; function-loader interface.
66;;
67;; Finally, Guile needs to load up at least some interfaces using
68;; dynamic-link / dynamic-pointer in order to be able to talk to the
69;; library at all (and to open a context in the case of Windows), and it
70;; happens that these interfaces also work fine for getting some of the
71;; GL functionality!
72;;
73;; All of this mess really has very little place in the world of free
74;; software, where dynamic linking is entirely sufficient to deal with
75;; this issue, but it is how things have evolved.
76;;
77;; In light of all of this, we need to make some simplifications.
78;;
79;; One is that each low-level function will have just one foreign
80;; function wrapper. This means that a minority of Windows
81;; configurations won't work. Oh well.
82;;
83;; Another is that if dynamic-link returns a result, that it is assumed
84;; that glXGetProcAddress (or the equivalent) would return the same
85;; value. So we can try dynamic-link first, and only dispatch to e.g
86;; glXGetProcAddress if that fails.
87;;
88;; Finally, we assume that all GL symbols may be resolved by
89;; dynamic-pointer by looking in one library, regardless of whether they
90;; come from the lower GL level or from the window-system-specific
91;; level.
92;;
93
94;; Parameterize this with glXGetProcAddress, eglGetProcAddress, etc.
95(define current-gl-resolver
96 (make-parameter (lambda (name) %null-pointer)))
97
98;; Parameterize this with a procedure that returns a dynamic object we
99;; can use to get libGL bindings.
100(define current-gl-get-dynamic-object
101 (make-parameter (lambda () (dynamic-link))))
102
103(define (resolve name)
104 (let ((ptr ((current-gl-resolver) (symbol->string name))))
105 (if (null-pointer? ptr)
106 (dynamic-pointer (symbol->string name)
107 ((current-gl-get-dynamic-object)))
108 ptr)))
109
110(define-syntax define-gl-procedure
111 (syntax-rules (->)
112 ((define-gl-procedure (name (pname ptype) ... -> type)
113 docstring)
114 (define-foreign-procedure (name (pname ptype) ... -> type)
115 (resolve 'name)
116 docstring))))
117
118(define-syntax define-gl-procedures
119 (syntax-rules ()
120 ((define-gl-procedures ((name prototype ...) ...)
121 docstring)
122 (begin
123 (define-gl-procedure (name prototype ...)
124 docstring)
125 ...))))