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         contextVersion = loadedVersion = GLSupport.noContext;
31     }
32 }
33 
34 GLSupport loadOpenGL()
35 {
36     version(Windows) {
37         const(char)[][1] libNames = ["OpenGL32.dll"];
38     }
39     else version(OSX) {
40         const(char)[][3] libNames = [
41             "../Frameworks/OpenGL.framework/OpenGL",
42             "/Library/Frameworks/OpenGL.framework/OpenGL",
43             "/System/Library/Frameworks/OpenGL.framework/OpenGL"
44         ];
45     }
46     else version(Posix) {
47         const(char)[][2] libNames = [
48             "libGL.so.1",
49             "libGL.so"
50         ];
51     }
52     else static assert(0, "bindbc-opengl is not yet supported on this platform");
53 
54     GLSupport ret;
55     foreach(name; libNames) {
56         ret = loadOpenGL(name.ptr);
57         if(ret != GLSupport.noLibrary) break;
58     }
59     return ret;
60 }
61 
62 GLSupport loadOpenGL(const(char)* libName)
63 {
64     import bindbc.opengl.bind;
65 
66     // If the library isn't yet loaded, load it now.
67     if(lib == invalidHandle) {
68         lib = load(libName);
69         if(lib == invalidHandle) {
70             return GLSupport.noLibrary;
71         }
72     }
73 
74     // Before attempting to load *any* symbols, make sure a context
75     // has been activated. This is only a requirement on Windows, and
76     // only in specific cases, but always checking for it makes for
77     // uniformity across platforms and no surprises when porting client
78     // code from other platforms to Windows.
79     contextVersion = getContextVersion(lib);
80     if(contextVersion < GLSupport.gl11) return contextVersion;
81 
82     // Load the base library
83     if(!lib.loadGL11()) return GLSupport.badLibrary;
84     else loadedVersion = GLSupport.gl11;
85 
86     // Now load the context-dependent stuff. `glSupport` is set to OpenGL 2.1
87     // by default and can't be lower. Load higher only if configured to do so.
88     with (GLSupport)
89     static foreach(ver; [ gl12, gl13, gl14, gl15, gl20, gl21, gl30, gl31,
90         gl32, gl33, gl40, gl41, gl42, gl43, gl44, gl45, gl46 ])
91     {
92         static if(ver <= glSupport)
93         {
94             // lib.loadGL30(contextVersion)
95             if(mixin("lib.loadGL" ~ (cast(int)ver).stringof ~ "(contextVersion)"))
96                 loadedVersion = ver;
97             else
98                 goto LoadARB;
99         }
100     }
101 
102     LoadARB:
103 
104     // From any GL versions higher than the one loaded, load the core ARB
105     // extensions.
106     with (GLSupport)
107     static foreach(ver; [ gl30, gl31, gl32, gl33, gl40, gl41, gl42, gl43,
108         gl44, gl45, gl46 ])
109     {
110         if(ver > loadedVersion)
111             // lib.loadARB30(contextVersion)
112             mixin("lib.loadARB" ~ (cast(int)ver).stringof ~ "(loadedVersion);");
113     }
114 
115     // Load all other supported extensions
116     loadARB(lib, contextVersion);
117     loadNV(lib, contextVersion);
118 
119     return loadedVersion;
120 }
121 
122 package:
123     SharedLib libGL() { return lib; }