]> git.tdb.fi Git - libs/gl.git/blob - source/extension.cpp
Immediate update camera aspect in View::set_camera
[libs/gl.git] / source / extension.cpp
1 #include <set>
2 #include <cstdlib>
3 #if defined(__ANDROID__)
4 #include <EGL/egl.h>
5 #elif !defined(_WIN32) && !defined(__APPLE__)
6 #define GLX_GLXEXT_PROTOTYPES
7 #include <GL/glx.h>
8 #endif
9 #include <msp/strings/format.h>
10 #include <msp/strings/utils.h>
11 #include "error.h"
12 #include "extension.h"
13 #include "gl.h"
14
15 using namespace std;
16
17 namespace Msp {
18 namespace GL {
19
20 Version::Version()
21 {
22         major = 0;
23         minor = 0;
24 }
25
26 Version::Version(unsigned short a, unsigned short i)
27 {
28         major = a;
29         minor = i;
30 }
31
32 Version::Version(const string &s)
33 {
34         vector<string> parts = split(s, '.');
35         major = lexical_cast<unsigned>(parts[0]);
36         minor = lexical_cast<unsigned>(parts[1]);
37 }
38
39 bool Version::operator>=(const Version &other) const
40 {
41         return major>other.major || (major==other.major && minor>=other.minor);
42 }
43
44
45 Extension::Extension(const char *n, InitFunc f):
46         name(n),
47         init_func(f),
48         init_done(false),
49         support(UNSUPPORTED)
50 { }
51
52 Extension::operator bool() const
53 {
54         if(!init_done)
55         {
56                 support = init_func();
57                 init_done = true;
58         }
59
60         return support>UNSUPPORTED;
61 }
62
63
64 Require::Require(const Extension &ext)
65 {
66         if(!ext)
67                 throw unsupported_extension(ext.get_name());
68 }
69
70
71 bool is_supported(const string &ext)
72 {
73         static set<string> extensions;
74         static bool init_done = false;
75
76         if(!init_done)
77         {
78                 if(get_gl_api()==OPENGL && get_gl_version()>=Version(3, 0))
79                 {
80                         typedef GLubyte *(APIENTRY *FPtr_glGetStringi)(GLenum, GLuint);
81                         FPtr_glGetStringi glGetStringi = reinterpret_cast<FPtr_glGetStringi>(get_proc_address("glGetStringi"));
82                         int n_extensions;
83                         glGetIntegerv(GL_NUM_EXTENSIONS, &n_extensions);
84                         for(int i=0; i<n_extensions; ++i)
85                                 extensions.insert(reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i)));
86                 }
87                 else
88                 {
89                         if(const char *gl_ext = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)))
90                         {
91                                 vector<string> exts = split(gl_ext);
92                                 extensions.insert(exts.begin(), exts.end());
93                         }
94                 }
95
96                 init_done = true;
97         }
98
99         return extensions.count(ext);
100 }
101
102 bool is_supported(const Version &core_version, const Version &deprecated_version)
103 {
104         const Version &version = get_gl_version();
105         if(deprecated_version && version>=deprecated_version && get_gl_profile()==CORE_PROFILE)
106                 return false;
107         return (version>=core_version);
108 }
109
110 bool is_disabled(const string &ext)
111 {
112         static set<string> disabled_exts;
113         static bool init_done = false;
114
115         if(!init_done)
116         {
117                 if(const char *disable_ptr = getenv("MSPGL_DISABLE_EXTENSIONS"))
118                 {
119                         vector<string> disable = split(disable_ptr);
120                         disabled_exts.insert(disable.begin(), disable.end());
121                 }
122
123                 if(const char *renderer_ptr = reinterpret_cast<const char *>(glGetString(GL_RENDERER)))
124                 {
125                         string renderer = renderer_ptr;
126                         if(renderer.find("Radeon")!=string::npos || renderer.find("AMD")!=string::npos)
127                         {
128                                 /* Radeon doesn't process NV_primitive_restart correctly and treats
129                                 the restart index as a normal element if the indices are stored in a
130                                 buffer. */
131                                 disabled_exts.insert("GL_NV_primitive_restart");
132
133                                 /* AMD's uniform buffer objects only work with the core version of
134                                 shaders. */
135                                 if(get_gl_version()<Version(2, 0))
136                                         disabled_exts.insert("GL_ARB_uniform_buffer_object");
137                         }
138                 }
139
140                 init_done = true;
141         }
142
143         return disabled_exts.count(ext);
144 }
145
146 GLApi get_gl_api()
147 {
148 #ifdef GL_ES_VERSION_2_0
149         return OPENGL_ES2;
150 #else
151         return OPENGL;
152 #endif
153 }
154
155 inline GLProfile _get_gl_profile()
156 {
157         if(get_gl_api()==OPENGL && get_gl_version()>=Version(3, 0))
158         {
159                 int mask;
160                 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
161                 if(mask==GL_CONTEXT_CORE_PROFILE_BIT)
162                         return CORE_PROFILE;
163         }
164
165         return COMPATIBILITY_PROFILE;
166 }
167
168 GLProfile get_gl_profile()
169 {
170         static GLProfile profile = _get_gl_profile();
171         return profile;
172 }
173
174 inline Version _get_gl_version()
175 {
176         const char *gl_ver_ptr = reinterpret_cast<const char *>(glGetString(GL_VERSION));
177         if(!gl_ver_ptr)
178                 throw runtime_error("OpenGL version not available");
179
180         string gl_ver = gl_ver_ptr;
181         if(!gl_ver.compare(0, 10, "OpenGL ES "))
182                 gl_ver.erase(0, 10);
183
184         Version ver(gl_ver.substr(0, gl_ver.find(' ')));
185
186         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_VERSION"))
187         {
188                 Version force_ver(force_ver_ptr);
189                 if(!(force_ver>=ver))
190                         ver = force_ver;
191         }
192
193         return ver;
194 }
195
196 const Version &get_gl_version()
197 {
198         static Version version = _get_gl_version();
199         return version;
200 }
201
202 inline Version _get_glsl_version()
203 {
204         const char *glsl_ver_ptr = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
205         if(!glsl_ver_ptr)
206                 throw runtime_error("GLSL version not available");
207
208         string glsl_ver = glsl_ver_ptr;
209         if(!glsl_ver.compare(0, 18, "OpenGL ES GLSL ES "))
210                 glsl_ver.erase(0, 18);
211
212         Version ver(glsl_ver.substr(0, glsl_ver.find(' ')));
213
214         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_GLSL_VERSION"))
215         {
216                 Version force_ver(force_ver_ptr);
217                 if(!(force_ver>=ver))
218                         ver = force_ver;
219         }
220
221         return ver;
222 }
223
224 const Version &get_glsl_version()
225 {
226         static Version version = _get_glsl_version();
227         return version;
228 }
229
230 ExtFunc *get_proc_address(const string &name)
231 {
232 #if defined(WIN32)
233         return reinterpret_cast<ExtFunc *>(wglGetProcAddress(name.c_str()));
234 #elif defined(__APPLE__)
235         (void)name;
236         return 0;  // Not supported
237 #elif defined(__ANDROID__)
238         return eglGetProcAddress(name.c_str());
239 #else
240         return glXGetProcAddressARB(reinterpret_cast<const unsigned char *>(name.c_str()));
241 #endif
242 }
243
244 } // namespace GL
245 } // namespace Msp