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