1 
2 //          Copyright 2018 - 2021 Michael D. Parker
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 module bindbc.opengl.gl;
8 
9 import bindbc.loader;
10 import bindbc.opengl.config,
11        bindbc.opengl.context;
12 
13 private {
14     SharedLib lib;
15     GLSupport contextVersion = GLSupport.noContext;
16     GLSupport loadedVersion = GLSupport.noContext;
17 }
18 
19 @nogc nothrow:
20 
21 GLSupport openGLContextVersion() { return contextVersion; }
22 GLSupport loadedOpenGLVersion() { return loadedVersion; }
23 bool isOpenGLLoaded() { return lib != invalidHandle; }
24 
25 
26 void unloadOpenGL()
27 {
28     if(lib != invalidHandle) {
29         lib.unload();
30         version(Posix) unloadContext();
31         contextVersion = loadedVersion = GLSupport.noContext;
32     }
33 }
34 
35 GLSupport loadOpenGL()
36 {
37     version(Windows) {
38         const(char)[][1] libNames = ["OpenGL32.dll"];
39     }
40     else version(OSX) {
41         const(char)[][3] libNames = [
42             "../Frameworks/OpenGL.framework/OpenGL",
43             "/Library/Frameworks/OpenGL.framework/OpenGL",
44             "/System/Library/Frameworks/OpenGL.framework/OpenGL"
45         ];
46     }
47     else version(Posix) {
48         const(char)[][2] libNames = [
49             "libGL.so.1",
50             "libGL.so"
51         ];
52     }
53     else static assert(0, "bindbc-opengl is not yet supported on this platform");
54 
55     GLSupport ret;
56     foreach(name; libNames) {
57         ret = loadOpenGL(name.ptr);
58         if(ret != GLSupport.noLibrary) break;
59     }
60     return ret;
61 }
62 
63 GLSupport loadOpenGL(const(char)* libName)
64 {
65     import bindbc.opengl.bind;
66 
67     // If the library isn't yet loaded, load it now.
68     if(lib == invalidHandle) {
69         lib = load(libName);
70         if(lib == invalidHandle) {
71             return GLSupport.noLibrary;
72         }
73     }
74 
75     // Before attempting to load *any* symbols, make sure a context
76     // has been activated. This is only a requirement on Windows, and
77     // only in specific cases, but always checking for it makes for
78     // uniformity across platforms and no surprises when porting client
79     // code from other platforms to Windows.
80     contextVersion = getContextVersion(lib);
81     if(contextVersion < GLSupport.gl11) return contextVersion;
82 
83     // Load the base library
84     if(!lib.loadGL11()) return GLSupport.badLibrary;
85     else loadedVersion = GLSupport.gl11;
86 
87     // Now load the context-dependent stuff. `glSupport` is set to OpenGL 2.1
88     // by default and can't be lower. Load higher only if configured to do so.
89     with (GLSupport)
90     static foreach(ver; [ gl12, gl13, gl14, gl15, gl20, gl21, gl30, gl31,
91         gl32, gl33, gl40, gl41, gl42, gl43, gl44, gl45, gl46 ])
92     {
93         static if(ver <= glSupport)
94         {
95             // lib.loadGL30(contextVersion)
96             if(mixin("lib.loadGL" ~ (cast(int)ver).stringof ~ "(contextVersion)"))
97                 loadedVersion = ver;
98             else
99                 goto LoadARB;
100         }
101     }
102 
103     LoadARB:
104 
105     // From any GL versions higher than the one loaded, load the core ARB
106     // extensions.
107     with (GLSupport)
108     static foreach(ver; [ gl30, gl31, gl32, gl33, gl40, gl41, gl42, gl43,
109         gl44, gl45, gl46 ])
110     {
111         if(ver > loadedVersion)
112             // lib.loadARB30(contextVersion)
113             mixin("lib.loadARB" ~ (cast(int)ver).stringof ~ "(loadedVersion);");
114     }
115 
116     // Load all other supported extensions
117     loadARB(lib, contextVersion);
118     loadNV(lib, contextVersion);
119     loadKHR(lib, contextVersion);
120 
121     return loadedVersion;
122 }
123 
124 package:
125     SharedLib libGL() { return lib; }