1 // glcontext.h
2 //
3 // Copyright (C) 2003, Chris Laurel <claurel@shatters.net>
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9
10 #include <algorithm>
11 #include <celutil/debug.h>
12 #include "gl.h"
13 #include "glext.h"
14 #include "glcontext.h"
15
16 using namespace std;
17
18
19 static VertexProcessor* vpNV = NULL;
20 static VertexProcessor* vpARB = NULL;
21 static FragmentProcessor* fpNV = NULL;
22
23
GLContext()24 GLContext::GLContext() :
25 renderPath(GLPath_Basic),
26 vertexPath(VPath_Basic),
27 vertexProc(NULL),
28 maxSimultaneousTextures(1)
29 {
30 }
31
~GLContext()32 GLContext::~GLContext()
33 {
34 }
35
36
init(const vector<string> & ignoreExt)37 void GLContext::init(const vector<string>& ignoreExt)
38 {
39 char* extensionsString = (char*) glGetString(GL_EXTENSIONS);
40 if (extensionsString != NULL)
41 {
42 char* next = extensionsString;
43
44 while (*next != '\0')
45 {
46 while (*next != '\0' && *next != ' ')
47 next++;
48
49 string ext(extensionsString, next - extensionsString);
50
51 // scan the ignore list
52 bool shouldIgnore = false;
53 for (vector<string>::const_iterator iter = ignoreExt.begin();
54 iter != ignoreExt.end(); iter++)
55 {
56 if (*iter == ext)
57 {
58 shouldIgnore = true;
59 break;
60 }
61 }
62
63 if (!shouldIgnore)
64 extensions.insert(extensions.end(), ext);
65
66 if (*next == '\0')
67 break;
68 next++;
69 extensionsString = next;
70 }
71 }
72
73 // Initialize all extensions used
74 for (vector<string>::const_iterator iter = extensions.begin();
75 iter != extensions.end(); iter++)
76 {
77 InitExtension(iter->c_str());
78 }
79
80 if (extensionSupported("GL_ARB_multitexture") &&
81 glx::glActiveTextureARB != NULL)
82 {
83 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB,
84 (GLint*) &maxSimultaneousTextures);
85 }
86
87 if (extensionSupported("GL_ARB_vertex_program") &&
88 glx::glGenProgramsARB)
89 {
90 DPRINTF(1, "Renderer: ARB vertex programs supported.\n");
91 if (vpARB == NULL)
92 vpARB = vp::initARB();
93 vertexProc = vpARB;
94 }
95 else if (extensionSupported("GL_NV_vertex_program") &&
96 glx::glGenProgramsNV)
97 {
98 DPRINTF(1, "Renderer: nVidia vertex programs supported.\n");
99 if (vpNV == NULL)
100 vpNV = vp::initNV();
101 vertexProc = vpNV;
102 }
103
104 if (extensionSupported("GL_NV_fragment_program") &&
105 glx::glGenProgramsNV)
106 {
107 DPRINTF(1, "Renderer: nVidia fragment programs supported.\n");
108 if (fpNV == NULL)
109 fpNV = fp::initNV();
110 fragmentProc = fpNV;
111 }
112
113 // Initialize GLX_SGI_video_sync blindly. At most, it will be null.
114 InitExtension("GLX_SGI_video_sync");
115 }
116
117
setRenderPath(GLRenderPath path)118 bool GLContext::setRenderPath(GLRenderPath path)
119 {
120 if (!renderPathSupported(path))
121 return false;
122
123 switch (path)
124 {
125 case GLPath_Basic:
126 case GLPath_Multitexture:
127 case GLPath_NvCombiner:
128 vertexPath = VPath_Basic;
129 break;
130 case GLPath_NvCombiner_NvVP:
131 vertexPath = VPath_NV;
132 break;
133 case GLPath_DOT3_ARBVP:
134 case GLPath_NvCombiner_ARBVP:
135 case GLPath_ARBFP_ARBVP:
136 case GLPath_NV30:
137 case GLPath_GLSL:
138 vertexPath = VPath_ARB;
139 break;
140 default:
141 return false;
142 }
143
144 renderPath = path;
145
146 return true;
147 }
148
149
renderPathSupported(GLRenderPath path) const150 bool GLContext::renderPathSupported(GLRenderPath path) const
151 {
152 switch (path)
153 {
154 case GLPath_Basic:
155 return true;
156
157 case GLPath_Multitexture:
158 return (maxSimultaneousTextures > 1 &&
159 ( extensionSupported("GL_EXT_texture_env_combine") ||
160 extensionSupported("GL_ARB_texture_env_combine")) );
161
162 case GLPath_NvCombiner:
163 return false;
164 /*
165 // No longer supported; all recent NVIDIA drivers also support
166 // the vertex_program extension, so the combiners-only path
167 // isn't necessary.
168 return extensionSupported("GL_NV_register_combiners");
169 */
170
171 case GLPath_DOT3_ARBVP:
172 return (extensionSupported("GL_ARB_texture_env_dot3") &&
173 extensionSupported("GL_ARB_vertex_program") &&
174 vertexProc != NULL);
175
176 case GLPath_NvCombiner_NvVP:
177 // If ARB_vertex_program is supported, don't report support for
178 // this render path.
179 return (extensionSupported("GL_NV_register_combiners") &&
180 extensionSupported("GL_NV_vertex_program") &&
181 !extensionSupported("GL_ARB_vertex_program") &&
182 vertexProc != NULL);
183
184 case GLPath_NvCombiner_ARBVP:
185 return (extensionSupported("GL_NV_register_combiners") &&
186 extensionSupported("GL_ARB_vertex_program") &&
187 vertexProc != NULL);
188
189 case GLPath_ARBFP_ARBVP:
190 return false;
191 /*
192 return (extensionSupported("GL_ARB_vertex_program") &&
193 extensionSupported("GL_ARB_fragment_program") &&
194 vertexProc != NULL);
195 */
196
197 case GLPath_NV30:
198 /* This render path is deprecated; GLSL is now preferred */
199 return false;
200 /*
201 return (extensionSupported("GL_ARB_vertex_program") &&
202 extensionSupported("GL_NV_fragment_program"));
203 */
204
205 case GLPath_GLSL:
206 return (extensionSupported("GL_ARB_shader_objects") &&
207 extensionSupported("GL_ARB_shading_language_100") &&
208 extensionSupported("GL_ARB_vertex_shader") &&
209 extensionSupported("GL_ARB_fragment_shader"));
210
211 default:
212 return false;
213 }
214 }
215
216
nextRenderPath()217 GLContext::GLRenderPath GLContext::nextRenderPath()
218 {
219 GLContext::GLRenderPath newPath = renderPath;
220
221 do {
222 newPath = (GLRenderPath) ((int) newPath + 1);;
223 if (newPath > GLPath_GLSL)
224 newPath = GLPath_Basic;
225 } while (newPath != renderPath && !renderPathSupported(newPath));
226
227 renderPath = newPath;
228
229 return renderPath;
230 }
231
232
extensionSupported(const string & ext) const233 bool GLContext::extensionSupported(const string& ext) const
234 {
235 return (find(extensions.begin(), extensions.end(), ext) != extensions.end());
236 }
237
238
bumpMappingSupported() const239 bool GLContext::bumpMappingSupported() const
240 {
241 return renderPath > GLPath_Multitexture;
242 }
243
244
getVertexPath() const245 GLContext::VertexPath GLContext::getVertexPath() const
246 {
247 return vertexPath;
248 }
249
250
getVertexProcessor() const251 VertexProcessor* GLContext::getVertexProcessor() const
252 {
253 return vertexPath == VPath_Basic ? NULL : vertexProc;
254 }
255
256
getFragmentProcessor() const257 FragmentProcessor* GLContext::getFragmentProcessor() const
258 {
259 if (renderPath == GLPath_NV30 /* || renderPath == GLPath_ARGFP_ARBVP */ )
260 return fragmentProc;
261 else
262 return NULL;
263 }
264