00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <math.h>
00026
00027 #include "OpenGLExtensions.h"
00028 #include "Inform.h"
00029 #include "utilities.h"
00030
00031 #if !defined(_MSC_VER) && !(defined(__APPLE__) && !defined (VMDMESA))
00032 #include <GL/glx.h>
00033 #endif
00034
00035 #if defined(__APPLE__)
00036 #import <mach-o/dyld.h> // needed by the getProcAddress code
00037 #import <string.h>
00038 #endif
00039
00041
00042 OpenGLExtensions::OpenGLExtensions(void) {
00043
00044 multitextureunits = 0;
00045 hasmultisample = 0;
00046 hasmultidrawext = 0;
00047 hasstencilbuffer = 0;
00048 hastex2d = 0;
00049 hastex3d = 0;
00050 hasrescalenormalext = 0;
00051 hasglarbtexnonpoweroftwo = 0;
00052 hascompiledvertexarrayext = 0;
00053 hasglpointparametersext = 0;
00054 hasglpointspritearb = 0;
00055 hasglshaderobjectsarb = 0;
00056 hasglshadinglangarb = 0;
00057 hasglvertexshaderarb = 0;
00058 hasglfragmentshaderarb = 0;
00059 hasglgeometryshader4arb = 0;
00060 hasglsampleshadingarb = 0;
00061 }
00062
00063
00064 OpenGLExtensions::~OpenGLExtensions(void) {
00065 }
00066
00067 int OpenGLExtensions::vmdQueryExtension(const char *extname) {
00068 char *excl = getenv("VMD_EXCL_GL_EXTENSIONS");
00069 if (!extname)
00070 return 0;
00071
00072
00073 if (excl != NULL) {
00074 char *endexcl = excl + strlen(excl);
00075 while (excl < endexcl) {
00076 size_t n = strcspn(excl, " ");
00077 if ((strlen(extname) == n) && (strncmp(extname, excl, n) == 0)) {
00078 return 0;
00079 }
00080 excl += (n + 1);
00081 }
00082 }
00083
00084
00085 char *ext = (char *) glGetString(GL_EXTENSIONS);
00086 if (ext != NULL) {
00087 char *endext = ext + strlen(ext);
00088 while (ext < endext) {
00089 size_t n = strcspn(ext, " ");
00090 if ((strlen(extname) == n) && (strncmp(extname, ext, n) == 0)) {
00091 return 1;
00092 break;
00093 }
00094 ext += (n + 1);
00095 }
00096 }
00097
00098 return 0;
00099 }
00100
00101 VMDGLXextFuncPtr OpenGLExtensions::vmdGetProcAddress(const char * procname) {
00102 if (!procname)
00103 return NULL;
00104
00105 #if defined(_MSC_VER)
00106
00107
00108
00109 return (VMDGLXextFuncPtr) wglGetProcAddress((LPCSTR) procname);
00110 #endif
00111
00112
00113
00114
00115
00116
00117 #if defined(__APPLE__)
00118
00119 #if defined(ARCH_MACOSX)
00120
00121
00122
00123 if (getenv("VMDMACENABLEEEXTENSIONS") == NULL) {
00124 return NULL;
00125 }
00126 #endif
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 #if 1 || !defined(ARCH_MACOSXX86_64)
00154 NSSymbol symbol;
00155 char *symbolName;
00156
00157 symbolName = (char *) calloc(1, strlen(procname) + 2);
00158 strcpy(symbolName+1, procname);
00159 symbolName[0] = '_';
00160 symbol = NULL;
00161 if (NSIsSymbolNameDefined(symbolName))
00162 symbol = NSLookupAndBindSymbol (symbolName);
00163 free(symbolName);
00164 return (VMDGLXextFuncPtr) (symbol ? NSAddressOfSymbol(symbol) : NULL);
00165 #endif
00166 #endif
00167
00168 #if !defined(_MSC_VER) && !defined(__APPLE__)
00169 #if !defined(__linux) && !defined(ARCH_FREEBSD) && !defined(ARCH_FREEBSDAMD64) && !defined(ARCH_SOLARISX86) && !defined(ARCH_SOLARISX86_64) && (defined(GLX_VERSION_1_4) || defined(ARCH_SOLARIS2))
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180 return glXGetProcAddress((const GLubyte *) procname);
00181 #else
00182
00183
00184 #if defined(GLX_ARB_get_proc_address)
00185
00186
00187
00188 return glXGetProcAddressARB((const GLubyte *) procname);
00189 #endif
00190
00191 #endif
00192 #endif
00193
00194 return NULL;
00195 }
00196
00197 void OpenGLExtensions::vmdQueryGLVersion(int *major, int *minor, int *release) {
00198 const char *p = (char *) glGetString(GL_VERSION);
00199
00200 *major = 1;
00201 *minor = 0;
00202 *release = 0;
00203
00204 if (p != NULL) {
00205 char *cp;
00206 cp = (char *) calloc(1, strlen(p) + 1);
00207 strcpy(cp, p);
00208
00209 char *np=cp;
00210 char *ep=cp;
00211
00212 while (np < (np + strlen(p))) {
00213 if (*np == ' ' || *np == '\0') {
00214 *np = '\0';
00215 ep = np;
00216 break;
00217 }
00218 np++;
00219 }
00220
00221 np = cp;
00222 char *lp=cp;
00223 int x=0;
00224 while (np <= ep) {
00225 if (*np == '.' || *np == '\0') {
00226 *np = '\0';
00227
00228 switch(x) {
00229 case 0:
00230 *major = atoi(lp);
00231 break;
00232
00233 case 1:
00234 *minor = atoi(lp);
00235 break;
00236
00237 case 2:
00238 *release = atoi(lp);
00239 break;
00240 }
00241 np++;
00242 lp = np;
00243 x++;
00244 continue;
00245 }
00246
00247 np++;
00248 }
00249
00250 free(cp);
00251 }
00252 }
00253
00254
00255 void OpenGLExtensions::find_renderer(void) {
00256
00257 oglrenderer = GENERIC;
00258 const char * rs = (const char *) glGetString(GL_RENDERER);
00259 const char * rv = (const char *) glGetString(GL_VENDOR);
00260 if ((rs != NULL) && (rv != NULL)) {
00261 if (strstr(rv, "ATI") != NULL) {
00262 oglrenderer = ATI;
00263 }
00264 if (strstr(rv, "NVIDIA") != NULL) {
00265 oglrenderer = NVIDIA;
00266 }
00267 if (strstr(rs, "GDI Generic") != NULL) {
00268 oglrenderer = MSOFTGDI;
00269 }
00270 if (strstr(rs, "Mesa") != NULL) {
00271 oglrenderer = MESAGL;
00272 }
00273 if (strstr(rs, "WireGL") != NULL) {
00274 oglrenderer = WIREGL;
00275 }
00276 }
00277 }
00278
00279
00280 void OpenGLExtensions::find_extensions(void) {
00281
00282 p_glLockArraysEXT = NULL;
00283 p_glUnlockArraysEXT = NULL;
00284 p_glMultiDrawElementsEXT = NULL;
00285 p_glGlobalAlphaFactorfSUN = NULL;
00286 p_glPointParameterfARB = NULL;
00287 p_glPointParameterfvARB = NULL;
00288
00289 #if defined(GL_ARB_shader_objects)
00290
00291 p_glCreateShaderObjectARB = NULL;
00292 p_glCreateProgramObjectARB = NULL;
00293 p_glUseProgramObjectARB = NULL;
00294 p_glDetachObjectARB = NULL;
00295 p_glGetInfoLogARB = NULL;
00296 p_glGetObjectParameterivARB = NULL;
00297 p_glLinkProgramARB = NULL;
00298 p_glDeleteObjectARB = NULL;
00299 p_glAttachObjectARB = NULL;
00300 p_glCompileShaderARB = NULL;
00301 p_glShaderSourceARB = NULL;
00302 p_glGetUniformLocationARB = NULL;
00303 p_glUniform1iARB = NULL;
00304 p_glUniform1fvARB = NULL;
00305 p_glUniform2fvARB = NULL;
00306 p_glUniform3fvARB = NULL;
00307 p_glUniform4fvARB = NULL;
00308 #endif
00309
00310 vmdQueryGLVersion(&oglmajor, &oglminor, &oglrelease);
00311
00312
00313 GLint stencilbits;
00314 glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
00315 if (stencilbits > 0) {
00316 hasstencilbuffer = 1;
00317 }
00318
00319
00320 find_renderer();
00321
00322 #if defined(GL_ARB_multitexture)
00323
00324
00325 if (((oglmajor >= 1) && (oglminor >= 2)) ||
00326 ((oglmajor >= 2) && (oglminor >= 0))) {
00327
00328 if (vmdQueryExtension("GL_ARB_multitexture")) {
00329 glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &multitextureunits);
00330 }
00331 }
00332 #endif
00333
00334 #if defined(GL_VERSION_1_1)
00335
00336
00337 if (((oglmajor >= 1) && (oglminor >= 1)) ||
00338 ((oglmajor >= 2) && (oglminor >= 0))) {
00339 hastex2d = 1;
00340 }
00341 #endif
00342
00343 #if defined(GL_VERSION_1_2)
00344
00345
00346 if (((oglmajor >= 1) && (oglminor >= 2)) ||
00347 ((oglmajor >= 2) && (oglminor >= 0))) {
00348 #if defined(VMDUSEGETPROCADDRESS) && !defined(__linux) && !defined(__APPLE__)
00349 p_glTexImage3D = (void (APIENTRY *)(GLenum, GLint, GLint,
00350 GLsizei, GLsizei, GLsizei, GLint,
00351 GLenum, GLenum, const GLvoid *)) vmdGetProcAddress("glTexImage3D");
00352 if (p_glTexImage3D != NULL) {
00353 hastex3d = 1;
00354 }
00355 #else
00356 hastex3d = 1;
00357 #endif
00358 }
00359 #endif
00360
00361 #if defined(GL_ARB_texture_non_power_of_two)
00362
00363 if (vmdQueryExtension("GL_ARB_texture_non_power_of_two")) {
00364 hasglarbtexnonpoweroftwo = 1;
00365 }
00366 #endif
00367
00368 #if defined(GL_EXT_multi_draw_arrays)
00369
00370 if (vmdQueryExtension("GL_EXT_multi_draw_arrays")) {
00371 #if defined(VMDUSEGETPROCADDRESS)
00372 p_glMultiDrawElementsEXT = (void (APIENTRY *)(GLenum, const GLsizei *, GLenum, const GLvoid**, GLsizei)) vmdGetProcAddress("glMultiDrawElementsEXT");
00373 if (p_glMultiDrawElementsEXT != NULL) {
00374 hasmultidrawext = 1;
00375 }
00376 #else
00377 hasmultidrawext = 1;
00378 #endif
00379 }
00380 #endif
00381
00382 #if defined(GL_ARB_shading_language_100)
00383
00384 if (vmdQueryExtension("GL_ARB_shading_language_100")) {
00385 hasglshadinglangarb = 1;
00386 }
00387 #endif
00388
00389 #if defined(GL_ARB_shader_objects)
00390 if (vmdQueryExtension("GL_ARB_shader_objects")) {
00391 #if defined(VMDUSEGETPROCADDRESS)
00392 p_glCreateShaderObjectARB = (GLhandleARB (APIENTRY *)(GLenum)) vmdGetProcAddress("glCreateShaderObjectARB");
00393 p_glCreateProgramObjectARB = (GLhandleARB (APIENTRY *)(void)) vmdGetProcAddress("glCreateProgramObjectARB");
00394 p_glUseProgramObjectARB = (void (APIENTRY *)(GLhandleARB)) vmdGetProcAddress("glUseProgramObjectARB");
00395 p_glDetachObjectARB = (void (APIENTRY *)(GLhandleARB, GLhandleARB)) vmdGetProcAddress("glDetachObjectARB");
00396 p_glGetInfoLogARB = (void (APIENTRY *)(GLhandleARB, GLsizei, GLsizei *, GLcharARB *)) vmdGetProcAddress("glGetInfoLogARB");
00397 p_glGetObjectParameterivARB = (void (APIENTRY *)(GLhandleARB, GLenum, GLint *)) vmdGetProcAddress("glGetObjectParameterivARB");
00398 p_glLinkProgramARB = (void (APIENTRY *)(GLhandleARB)) vmdGetProcAddress("glLinkProgramARB");
00399 p_glDeleteObjectARB = (void (APIENTRY *)(GLhandleARB)) vmdGetProcAddress("glDeleteObjectARB");
00400 p_glAttachObjectARB = (void (APIENTRY *)(GLhandleARB, GLhandleARB)) vmdGetProcAddress("glAttachObjectARB");
00401 p_glCompileShaderARB = (void (APIENTRY *)(GLhandleARB)) vmdGetProcAddress("glCompileShaderARB");
00402 p_glShaderSourceARB = (void (APIENTRY *)(GLhandleARB, GLsizei, const GLcharARB **, const GLint *)) vmdGetProcAddress("glShaderSourceARB");
00403 p_glGetUniformLocationARB = (GLint (APIENTRY *)(GLhandleARB programObject, const GLcharARB *name)) vmdGetProcAddress("glGetUniformLocationARB");
00404 p_glUniform1iARB = (void (APIENTRY *)(GLint location, GLint v0)) vmdGetProcAddress("glUniform1iARB");
00405 p_glUniform1fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) vmdGetProcAddress("glUniform1fvARB");
00406 p_glUniform2fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) vmdGetProcAddress("glUniform2fvARB");
00407 p_glUniform3fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) vmdGetProcAddress("glUniform3fvARB");
00408 p_glUniform4fvARB = (void (APIENTRY *)(GLint location, GLsizei count, GLfloat *value)) vmdGetProcAddress("glUniform4fvARB");
00409
00410 if (p_glCreateShaderObjectARB != NULL && p_glCreateProgramObjectARB != NULL &&
00411 p_glUseProgramObjectARB != NULL && p_glDetachObjectARB != NULL &&
00412 p_glGetInfoLogARB != NULL && p_glGetObjectParameterivARB != NULL &&
00413 p_glLinkProgramARB != NULL && p_glDeleteObjectARB != NULL &&
00414 p_glAttachObjectARB != NULL && p_glCompileShaderARB != NULL &&
00415 p_glShaderSourceARB != NULL && p_glGetUniformLocationARB != NULL &&
00416 p_glUniform1iARB != NULL && p_glUniform1fvARB != NULL &&
00417 p_glUniform2fvARB != NULL && p_glUniform3fvARB != NULL &&
00418 p_glUniform4fvARB != NULL) {
00419 hasglshaderobjectsarb = 1;
00420 } else {
00421 hasglshaderobjectsarb = 0;
00422 }
00423 #else
00424 hasglshaderobjectsarb = 1;
00425 #endif
00426 }
00427 #endif
00428
00429 #if defined(GL_ARB_vertex_shader)
00430 if (vmdQueryExtension("GL_ARB_vertex_shader")) {
00431 hasglvertexshaderarb = 1;
00432 }
00433 #endif
00434
00435 #if defined(GL_ARB_fragment_shader)
00436 if (vmdQueryExtension("GL_ARB_fragment_shader")) {
00437 hasglfragmentshaderarb = 1;
00438 }
00439 #endif
00440
00441 #if defined(GL_ARB_geometry_shader4)
00442 if (vmdQueryExtension("GL_ARB_geometry_shader4")) {
00443 hasglgeometryshader4arb = 1;
00444 }
00445 #endif
00446
00447 if (vmdQueryExtension("GL_ARB_sample_shading")) {
00448 hasglsampleshadingarb = 1;
00449 }
00450
00451
00452 #if defined(GL_EXT_compiled_vertex_array)
00453
00454 if (vmdQueryExtension("GL_EXT_compiled_vertex_array")) {
00455 #if defined(VMDUSEGETPROCADDRESS)
00456 p_glLockArraysEXT = (void (APIENTRY *)(GLint, GLsizei)) vmdGetProcAddress("glLockArraysEXT");
00457 p_glUnlockArraysEXT = (void (APIENTRY *)(void)) vmdGetProcAddress("glUnlockArraysEXT");
00458 if ((p_glLockArraysEXT != NULL) && (p_glUnlockArraysEXT != NULL)) {
00459 hascompiledvertexarrayext = 1;
00460 }
00461 #else
00462 hascompiledvertexarrayext = 1;
00463 #endif
00464 }
00465 #endif
00466
00467 #if defined(GL_ARB_point_parameters)
00468
00469 if (vmdQueryExtension("GL_ARB_point_parameters")) {
00470 #if defined(VMDUSEGETPROCADDRESS)
00471 p_glPointParameterfARB = (void (APIENTRY *)(GLenum, GLfloat)) vmdGetProcAddress("glPointParameterfARB");
00472 p_glPointParameterfvARB = (void (APIENTRY *)(GLenum, const GLfloat *)) vmdGetProcAddress("glPointParameterfvARB");
00473 if (p_glPointParameterfARB != NULL && p_glPointParameterfvARB != NULL) {
00474 hasglpointparametersext = 1;
00475 }
00476 #else
00477 hasglpointparametersext = 1;
00478 #endif
00479 }
00480 #endif
00481
00482 #if defined(GL_ARB_point_sprite)
00483 if (vmdQueryExtension("GL_ARB_point_sprite")) {
00484 hasglpointspritearb = 1;
00485 }
00486 #endif
00487
00488 }
00489
00490
00491 void OpenGLExtensions::PrintExtensions(void) {
00492 const char * rs = (const char *) glGetString(GL_RENDERER);
00493 if (rs == NULL)
00494 rs = "ErrorUnknown";
00495
00496
00497 msgInfo << "OpenGL renderer: " << rs << sendmsg;
00498
00499
00500 msgInfo << " Features: ";
00501 if (hasstencilbuffer)
00502 msgInfo << "STENCIL ";
00503
00504 if (hasstereo)
00505 msgInfo << "STEREO ";
00506
00507 if (hasmultisample)
00508 msgInfo << "MSAA(" << nummultisamples << ") ";
00509
00510 if (hasrescalenormalext)
00511 msgInfo << "RN ";
00512
00513 if (hasmultidrawext)
00514 msgInfo << "MDE ";
00515
00516 if (hascompiledvertexarrayext)
00517 msgInfo << "CVA ";
00518
00519 if (multitextureunits > 0)
00520 msgInfo << "MTX ";
00521
00522 if (hasglarbtexnonpoweroftwo)
00523 msgInfo << "NPOT ";
00524
00525 if (hasglpointparametersext)
00526 msgInfo << "PP ";
00527
00528 if (hasglpointspritearb)
00529 msgInfo << "PS ";
00530
00531
00532
00533
00534 if (hasglshadinglangarb) {
00535 msgInfo << "GLSL(";
00536
00537 if (hasglshaderobjectsarb)
00538 msgInfo << "O";
00539
00540 if (hasglvertexshaderarb)
00541 msgInfo << "V";
00542
00543 if (hasglfragmentshaderarb)
00544 msgInfo << "F";
00545
00546 if (hasglgeometryshader4arb)
00547 msgInfo << "G";
00548
00549 if (hasglsampleshadingarb)
00550 msgInfo << "S";
00551
00552 msgInfo << ") ";
00553 }
00554 msgInfo << sendmsg;
00555 }
00556