]> git.tdb.fi Git - libs/gl.git/blob - source/extension.cpp
Check glGetString result for being null
[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(const char *gl_ext = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)))
79                 {
80                         vector<string> exts = split(gl_ext);
81                         extensions.insert(exts.begin(), exts.end());
82                 }
83
84                 if(const char *renderer_ptr = reinterpret_cast<const char *>(glGetString(GL_RENDERER)))
85                 {
86                         string renderer = renderer_ptr;
87                         if(renderer.find("Radeon")!=string::npos || renderer.find("AMD")!=string::npos)
88                         {
89                                 /* Radeon doesn't process NV_primitive_restart correctly and treats
90                                 the restart index as a normal element if the indices are stored in a
91                                 buffer. */
92                                 extensions.erase("GL_NV_primitive_restart");
93
94                                 /* AMD's uniform buffer objects only work with the core version of
95                                 shaders. */
96                                 if(!(get_gl_version()>=Version(2, 0)))
97                                         extensions.erase("GL_ARB_uniform_buffer_object");
98                         }
99                 }
100
101                 if(const char *disable_ptr = getenv("MSPGL_DISABLE_EXTENSIONS"))
102                 {
103                         vector<string> disable = split(disable_ptr);
104                         for(vector<string>::const_iterator i=disable.begin(); i!=disable.end(); ++i)
105                                 extensions.erase(*i);
106                 }
107
108                 init_done = true;
109         }
110
111         return extensions.count(ext);
112 }
113
114 GLApi get_gl_api()
115 {
116 #ifdef GL_ES_VERSION_2_0
117         return OPENGL_ES2;
118 #else
119         return OPENGL;
120 #endif
121 }
122
123 inline Version _get_gl_version()
124 {
125         const char *gl_ver_ptr = reinterpret_cast<const char *>(glGetString(GL_VERSION));
126         if(!gl_ver_ptr)
127                 throw runtime_error("OpenGL version not available");
128
129         string gl_ver = gl_ver_ptr;
130         if(!gl_ver.compare(0, 10, "OpenGL ES "))
131                 gl_ver.erase(0, 10);
132
133         Version ver(gl_ver.substr(0, gl_ver.find(' ')));
134
135         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_VERSION"))
136         {
137                 Version force_ver(force_ver_ptr);
138                 if(!(force_ver>=ver))
139                         ver = force_ver;
140         }
141
142         return ver;
143 }
144
145 const Version &get_gl_version()
146 {
147         static Version version = _get_gl_version();
148         return version;
149 }
150
151 inline Version _get_glsl_version()
152 {
153         const char *glsl_ver_ptr = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
154         if(!glsl_ver_ptr)
155                 throw runtime_error("GLSL version not available");
156
157         string glsl_ver = glsl_ver_ptr;
158         if(!glsl_ver.compare(0, 18, "OpenGL ES GLSL ES "))
159                 glsl_ver.erase(0, 18);
160
161         Version ver(glsl_ver.substr(0, glsl_ver.find(' ')));
162
163         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_GLSL_VERSION"))
164         {
165                 Version force_ver(force_ver_ptr);
166                 if(!(force_ver>=ver))
167                         ver = force_ver;
168         }
169
170         return ver;
171 }
172
173 const Version &get_glsl_version()
174 {
175         static Version version = _get_glsl_version();
176         return version;
177 }
178
179 bool is_version_at_least(unsigned a, unsigned b)
180 {
181         return get_gl_version()>=Version(a, b);
182 }
183
184 ExtFunc *get_proc_address(const string &name)
185 {
186 #if defined(WIN32)
187         return reinterpret_cast<ExtFunc *>(wglGetProcAddress(name.c_str()));
188 #elif defined(__APPLE__)
189         (void)name;
190         return 0;  // Not supported
191 #elif defined(__ANDROID__)
192         return eglGetProcAddress(name.c_str());
193 #else
194         return glXGetProcAddressARB(reinterpret_cast<const unsigned char *>(name.c_str()));
195 #endif
196 }
197
198 } // namespace GL
199 } // namespace Msp