]> git.tdb.fi Git - libs/gl.git/blob - source/extension.cpp
Tweak extension behavior on Radeon
[libs/gl.git] / source / extension.cpp
1 #include <set>
2 #if !defined(WIN32) && !defined(__APPLE__)
3 #define GLX_GLXEXT_PROTOTYPES
4 #include <GL/glx.h>
5 #endif
6 #include <msp/strings/format.h>
7 #include <msp/strings/utils.h>
8 #include "error.h"
9 #include "extension.h"
10 #include "gl.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 Version::Version()
18 {
19         major = 0;
20         minor = 0;
21 }
22
23 Version::Version(unsigned short a, unsigned short i)
24 {
25         major = a;
26         minor = i;
27 }
28
29 Version::Version(const string &s)
30 {
31         vector<string> parts = split(s, '.');
32         major = lexical_cast<unsigned>(parts[0]);
33         minor = lexical_cast<unsigned>(parts[1]);
34 }
35
36 bool Version::operator>=(const Version &other) const
37 {
38         return major>other.major || (major==other.major && minor>=other.minor);
39 }
40
41
42 Extension::Extension(const char *n, InitFunc f):
43         name(n),
44         init_func(f),
45         init_done(false),
46         support(UNSUPPORTED)
47 { }
48
49 Extension::operator bool() const
50 {
51         if(!init_done)
52         {
53                 support = init_func();
54                 init_done = true;
55         }
56
57         return support>UNSUPPORTED;
58 }
59
60
61 Require::Require(const Extension &ext)
62 {
63         if(!ext)
64                 throw unsupported_extension(ext.get_name());
65 }
66
67
68 bool is_supported(const string &ext)
69 {
70         static set<string> extensions;
71         static bool init_done = false;
72
73         if(!init_done)
74         {
75                 if(const char *gl_ext = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)))
76                 {
77                         vector<string> exts = split(gl_ext);
78                         extensions.insert(exts.begin(), exts.end());
79                 }
80
81                 string renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
82                 if(renderer.find("Radeon")!=string::npos)
83                 {
84                         /* Radeon doesn't process NV_primitive_restart correctly and treats
85                         the restart index as a normal element if the indices are stored in a
86                         buffer. */
87                         extensions.erase("GL_NV_primitive_restart");
88
89                         /* AMD's uniform buffer objects only work with the core version of
90                         shaders. */
91                         if(!(get_gl_version()>=Version(2, 0)))
92                                 extensions.erase("GL_ARB_uniform_buffer_object");
93                 }
94
95                 if(const char *disable_ptr = getenv("MSPGL_DISABLE_EXTENSIONS"))
96                 {
97                         vector<string> disable = split(disable_ptr);
98                         for(vector<string>::const_iterator i=disable.begin(); i!=disable.end(); ++i)
99                                 extensions.erase(*i);
100                 }
101
102                 init_done = true;
103         }
104
105         return extensions.count(ext);
106 }
107
108 inline Version _get_gl_version()
109 {
110         string gl_ver = reinterpret_cast<const char *>(glGetString(GL_VERSION));
111         Version ver(gl_ver.substr(0, gl_ver.find(' ')));
112
113         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_VERSION"))
114         {
115                 Version force_ver(force_ver_ptr);
116                 if(!(force_ver>=ver))
117                         ver = force_ver;
118         }
119
120         return ver;
121 }
122
123 const Version &get_gl_version()
124 {
125         static Version version = _get_gl_version();
126         return version;
127 }
128
129 inline Version _get_glsl_version()
130 {
131         string glsl_ver = reinterpret_cast<const char *>(glGetString(GL_SHADING_LANGUAGE_VERSION));
132         Version ver(glsl_ver.substr(0, glsl_ver.find(' ')));
133
134         if(const char *force_ver_ptr = getenv("MSPGL_FORCE_GLSL_VERSION"))
135         {
136                 Version force_ver(force_ver_ptr);
137                 if(!(force_ver>=ver))
138                         ver = force_ver;
139         }
140
141         return ver;
142 }
143
144 const Version &get_glsl_version()
145 {
146         static Version version = _get_glsl_version();
147         return version;
148 }
149
150 bool is_version_at_least(unsigned a, unsigned b)
151 {
152         return get_gl_version()>=Version(a, b);
153 }
154
155 ExtFunc *get_proc_address(const string &name)
156 {
157 #if defined(WIN32)
158         return reinterpret_cast<ExtFunc *>(wglGetProcAddress(name.c_str()));
159 #elif defined(__APPLE__)
160         (void)name;
161         return 0;  // Not supported
162 #else
163         return glXGetProcAddressARB(reinterpret_cast<const unsigned char *>(name.c_str()));
164 #endif
165 }
166
167 } // namespace GL
168 } // namespace Msp