00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00027 #include <stdlib.h>
00028 #include <math.h>
00029 #include <GL/gl.h>
00030 
00031 #if defined(VMDGLXPBUFFER)
00032 #include <GL/glx.h>
00033 #include <X11/Xlib.h>
00034 #endif
00035 
00036 #include "OpenGLPbufferDisplayDevice.h"
00037 #include "Inform.h"
00038 #include "utilities.h"
00039 #include "config.h"   
00040 #include "VMDApp.h"
00041 #include "VideoStream.h" 
00042 
00043 
00044 #define DEF_PBUFFER_XRES 4096
00045 #define DEF_PBUFFER_YRES 2400
00046 
00047 
00048 static const char *glStereoNameStr[OPENGL_STEREO_MODES] =
00049  { "Off",
00050    "QuadBuffered",
00051    "HDTV SideBySide",
00052    "Checkerboard",
00053    "ColumnInterleaved",
00054    "RowInterleaved",
00055    "Anaglyph",
00056    "SideBySide",
00057    "AboveBelow",
00058    "Left",
00059    "Right" };
00060 
00061 static const char *glRenderNameStr[OPENGL_RENDER_MODES] = 
00062 { "Normal",
00063   "GLSL",
00064   "Acrobat3D" };
00065 
00066 static const char *glCacheNameStr[OPENGL_CACHE_MODES] = 
00067 { "Off",
00068   "On" };
00069 
00070 
00071 
00072 
00073 
00074 #if defined(VMDGLXPBUFFER)
00075 
00076 
00077 
00078 #if defined(GL_ARB_multisample) && defined(GLX_SAMPLES_ARB) && defined(GLX_SAMPLE_BUFFERS_ARB)
00079 #define USEARBMULTISAMPLE 1
00080 #endif
00081 
00082 static GLXFBConfig * vmd_get_glx_fbconfig(glxpbufferdata *glxsrv, int *stereo, int *msamp, int *numsamples) {
00083   
00084   int ns, dsize;
00085   int simplegraphics = 0;
00086   int disablestereo = 0;
00087   GLXFBConfig *fbc = NULL;
00088   int nfbc = 0;
00089 
00090   *numsamples = 0;
00091   *msamp = FALSE; 
00092   *stereo = FALSE;
00093 
00094   if (getenv("VMDSIMPLEGRAPHICS")) {
00095     simplegraphics = 1;
00096   }
00097 
00098   if (getenv("VMDDISABLESTEREO")) {
00099     disablestereo = 1;
00100   } 
00101 
00102   
00103   int maxaasamples=4;
00104   const char *maxaasamplestr = getenv("VMDMAXAASAMPLES");
00105   if (maxaasamplestr) {
00106     int aatmp;
00107     if (sscanf(maxaasamplestr, "%d", &aatmp) == 1) {
00108       if (aatmp >= 0) {
00109         maxaasamples=aatmp;
00110         msgInfo << "User-requested OpenGL antialiasing sample depth: " 
00111                 << maxaasamples << sendmsg;
00112 
00113         if (maxaasamples < 2) {
00114           maxaasamples=1; 
00115           msgInfo << "OpenGL antialiasing disabled by user override."
00116                   << sendmsg;
00117         }
00118       } else {
00119         msgErr << "Ignoring user-requested OpenGL antialiasing sample depth: " 
00120                << aatmp << sendmsg;
00121       }
00122     } else {
00123       msgErr << "Unable to parse override of OpenGL antialiasing" << sendmsg;
00124       msgErr << "sample depth: '" << maxaasamplestr << "'" << sendmsg;
00125     }
00126   }
00127 
00128 
00129   
00130   
00131   for (dsize=32; dsize >= 16; dsize-=4) { 
00132 
00133 
00134 #if defined(USEARBMULTISAMPLE) 
00135     if (!simplegraphics && !disablestereo && (!fbc && nfbc < 1)) {
00136       
00137       for (ns=maxaasamples; ns>1; ns--) {
00138         int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00139                        GLX_DOUBLEBUFFER, 1,
00140                        GLX_RENDER_TYPE, GLX_RGBA_BIT,
00141                        GLX_DEPTH_SIZE, dsize, 
00142                        GLX_STEREO, 1,
00143                        GLX_STENCIL_SIZE, 1, 
00144                        GLX_SAMPLE_BUFFERS_ARB, 1, 
00145                        GLX_SAMPLES_ARB, ns, 
00146                        GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00147                        None};
00148 
00149         fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00150 
00151         if (fbc && nfbc > 0) {
00152           *numsamples = ns;
00153           *msamp = TRUE;
00154           *stereo = TRUE;
00155           break; 
00156         } 
00157       }
00158     }
00159 #endif
00160 
00161     if (getenv("VMDPREFERSTEREO") != NULL && !disablestereo) {
00162       
00163       
00164       
00165       
00166       
00167       if (!simplegraphics && (!fbc && nfbc < 1)) {
00168         int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00169                        GLX_DOUBLEBUFFER, 1,
00170                        GLX_RENDER_TYPE, GLX_RGBA_BIT,
00171                        GLX_DEPTH_SIZE, dsize, 
00172                        GLX_STEREO, 1,
00173                        GLX_STENCIL_SIZE, 1, 
00174                        GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00175                        None};
00176 
00177         fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00178 
00179         ns = 0; 
00180         *numsamples = ns;
00181         *msamp = FALSE; 
00182         *stereo = TRUE; 
00183       }
00184     } 
00185 #if defined(USEARBMULTISAMPLE) 
00186     else {
00187       
00188       if (!simplegraphics && (!fbc && nfbc < 1)) {
00189         
00190         for (ns=maxaasamples; ns>1; ns--) {
00191           int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00192                          GLX_DOUBLEBUFFER, 1,
00193                          GLX_RENDER_TYPE, GLX_RGBA_BIT,
00194                          GLX_DEPTH_SIZE, dsize, 
00195                          GLX_STENCIL_SIZE, 1, 
00196                          GLX_SAMPLE_BUFFERS_ARB, 1, 
00197                          GLX_SAMPLES_ARB, ns, 
00198                          GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00199                          None};
00200 
00201           fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00202     
00203           if (fbc && nfbc > 0) {
00204             *numsamples = ns;
00205             *msamp = TRUE;
00206             *stereo = FALSE; 
00207             break; 
00208           } 
00209         }
00210       }
00211     }
00212 #endif
00213 
00214   } 
00215 
00216   
00217   
00218   
00219 
00220   
00221   if (!simplegraphics && !disablestereo && (!fbc && nfbc < 1)) {
00222     int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00223                    GLX_DOUBLEBUFFER, 1,
00224                    GLX_RENDER_TYPE, GLX_RGBA_BIT,
00225                    GLX_DEPTH_SIZE, 16, 
00226                    GLX_STEREO, 1,
00227                    GLX_STENCIL_SIZE, 1, 
00228                    GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00229                    None};
00230 
00231     fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00232     
00233     ns = 0; 
00234     *numsamples = ns;
00235     *msamp = FALSE; 
00236     *stereo = TRUE; 
00237   }
00238 
00239   
00240   if (!simplegraphics && !disablestereo && (!fbc && nfbc < 1)) {
00241     int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00242                    GLX_DOUBLEBUFFER, 1,
00243                    GLX_RENDER_TYPE, GLX_RGBA_BIT,
00244                    GLX_DEPTH_SIZE, 16, 
00245                    GLX_STEREO, 1,
00246                    GLX_STENCIL_SIZE, 1, 
00247                    GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
00248                    None};
00249 
00250     fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00251 
00252     ns = 0; 
00253     *numsamples = ns;
00254     *msamp = FALSE; 
00255     *stereo = TRUE; 
00256   }
00257 
00258   
00259   
00260   
00261   
00262   if (!simplegraphics && !disablestereo && (!fbc && nfbc < 1)) {
00263     int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00264                    GLX_DOUBLEBUFFER, 1,
00265                    GLX_RENDER_TYPE, GLX_RGBA_BIT,
00266                    GLX_DEPTH_SIZE, 16, 
00267                    GLX_STEREO, 1,
00268                    GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
00269                    None};
00270 
00271     fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00272 
00273     ns = 0; 
00274     *numsamples = ns;
00275     *msamp = FALSE; 
00276     *stereo = TRUE; 
00277   }
00278 
00279   
00280   
00281   if (!simplegraphics && (!fbc && nfbc < 1)) {
00282     int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00283                    GLX_DOUBLEBUFFER, 1,
00284                    GLX_RENDER_TYPE, GLX_RGBA_BIT,
00285                    GLX_DEPTH_SIZE, 16, 
00286                    GLX_STENCIL_SIZE, 1, 
00287                    GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00288                    None};
00289 
00290     fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00291 
00292     ns = 0; 
00293     *numsamples = ns;
00294     *msamp = FALSE; 
00295     *stereo = FALSE;
00296   }
00297   
00298   
00299   if (!fbc && nfbc < 1) {
00300     
00301     
00302     
00303     
00304     int conf[]  = {GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
00305                    GLX_DOUBLEBUFFER, 1,
00306                    GLX_RENDER_TYPE, GLX_RGBA_BIT,
00307                    GLX_DEPTH_SIZE, 16, 
00308                    GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8,
00309                    None};
00310 
00311     fbc = glXChooseFBConfig(glxsrv->dpy, glxsrv->dpyScreen, conf, &nfbc);
00312 
00313     ns = 0; 
00314     *numsamples = ns;
00315     *msamp = FALSE; 
00316     *stereo = FALSE;
00317   }
00318 
00319   if (!fbc && nfbc < 1) {
00320     
00321     ns = 0; 
00322     *numsamples = ns;
00323     *msamp = FALSE; 
00324     *stereo = FALSE;
00325   }
00326 
00327   
00328   if (nfbc < 1)
00329     return NULL;
00330 
00331   return fbc;
00332 }
00333 
00334 #endif
00335 
00336 
00337 
00338 
00339 
00340 #if defined(VMDEGLPBUFFER)
00341 
00342 
00343 
00344 #if defined(GL_ARB_multisample)
00345 #define USEARBMULTISAMPLE 1
00346 #endif
00347 
00348 static int vmd_get_egl_fbconfig(eglpbufferdata *eglsrv, int *stereo, int *msamp, int *numsamples) {
00349   
00350   int ns, dsize;
00351   int simplegraphics = 0;
00352   
00353   
00354   int fbc = 0;
00355   int nfbc = 0;
00356 
00357   *numsamples = 0;
00358   *msamp = FALSE; 
00359   *stereo = FALSE;
00360 
00361   if (getenv("VMDSIMPLEGRAPHICS")) {
00362     simplegraphics = 1;
00363   }
00364 
00365   
00366   
00367   
00368   
00369 
00370   
00371   int maxaasamples=4;
00372   const char *maxaasamplestr = getenv("VMDMAXAASAMPLES");
00373   if (maxaasamplestr) {
00374     int aatmp;
00375     if (sscanf(maxaasamplestr, "%d", &aatmp) == 1) {
00376       if (aatmp >= 0) {
00377         maxaasamples=aatmp;
00378         msgInfo << "User-requested OpenGL antialiasing sample depth: " 
00379                 << maxaasamples << sendmsg;
00380 
00381         if (maxaasamples < 2) {
00382           maxaasamples=1; 
00383           msgInfo << "OpenGL antialiasing disabled by user override."
00384                   << sendmsg;
00385         }
00386       } else {
00387         msgErr << "Ignoring user-requested OpenGL antialiasing sample depth: " 
00388                << aatmp << sendmsg;
00389       }
00390     } else {
00391       msgErr << "Unable to parse override of OpenGL antialiasing" << sendmsg;
00392       msgErr << "sample depth: '" << maxaasamplestr << "'" << sendmsg;
00393     }
00394   }
00395 
00396 
00397   
00398   
00399   for (dsize=32; dsize >= 16; dsize-=4) { 
00400     
00401     
00402     
00403     
00404 
00405 
00406 #if defined(USEARBMULTISAMPLE) 
00407     if (!simplegraphics && (!fbc && nfbc < 1)) {
00408       
00409       for (ns=maxaasamples; ns>1; ns--) {
00410         int conf[]  = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
00411                        EGL_DEPTH_SIZE, dsize, 
00412                        EGL_STENCIL_SIZE, 1, 
00413                        EGL_SAMPLE_BUFFERS, 1, 
00414                        EGL_SAMPLES, ns, 
00415                        EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
00416                        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE };
00417 
00418         if (eglChooseConfig(eglsrv->dpy, conf, &eglsrv->conf, 1, &nfbc) == EGL_TRUE) {
00419           if (nfbc > 0) {
00420             fbc=1; 
00421             *numsamples = ns;
00422             *msamp = TRUE;
00423             *stereo = FALSE; 
00424             break; 
00425           } 
00426         }
00427       }
00428     }
00429 #endif
00430 
00431     
00432     
00433     
00434     
00435   } 
00436 
00437   
00438   
00439   
00440 
00441   
00442   
00443   
00444   
00445 
00446   
00447   
00448   if (!simplegraphics && (!fbc && nfbc < 1)) {
00449     int conf[]  = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
00450                    EGL_DEPTH_SIZE, 16, 
00451                    EGL_STENCIL_SIZE, 1, 
00452                    EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
00453                    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE };
00454 
00455     if (eglChooseConfig(eglsrv->dpy, conf, &eglsrv->conf, 1, &nfbc) == EGL_TRUE) {
00456       if (nfbc > 0) {
00457         fbc=1; 
00458         ns = 0; 
00459         *numsamples = ns;
00460         *msamp = FALSE; 
00461         *stereo = FALSE; 
00462       } 
00463     }
00464   }
00465   
00466   
00467   if (!fbc && nfbc < 1) {
00468     
00469     
00470     
00471     
00472     int conf[]  = {EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
00473                    EGL_DEPTH_SIZE, 16, 
00474                    EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
00475                    EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, EGL_NONE };
00476 
00477     if (eglChooseConfig(eglsrv->dpy, conf, &eglsrv->conf, 1, &nfbc) == EGL_TRUE) {
00478       if (nfbc > 0) {
00479         fbc=1; 
00480         ns = 0; 
00481         *numsamples = ns;
00482         *msamp = FALSE; 
00483         *stereo = FALSE; 
00484       } 
00485     }
00486   }
00487 
00488   if (!fbc && nfbc < 1) {
00489     
00490     ns = 0; 
00491     *numsamples = ns;
00492     *msamp = FALSE; 
00493     *stereo = FALSE; 
00494   }
00495 
00496   
00497   if (nfbc < 1)
00498     return 0;
00499 
00500   return 1;
00501 }
00502 
00503 #endif
00504 
00505 
00506 
00507 
00508 
00509 
00510 
00511 
00512 
00514 
00515 OpenGLPbufferDisplayDevice::OpenGLPbufferDisplayDevice()
00516 : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {
00517   
00518   stereoNames = glStereoNameStr;
00519   stereoModes = OPENGL_STEREO_MODES;
00520 
00521   renderNames = glRenderNameStr;
00522   renderModes = OPENGL_RENDER_MODES;
00523 
00524   cacheNames = glCacheNameStr;
00525   cacheModes = OPENGL_CACHE_MODES;
00526 
00527 #if defined(VMDEGLPBUFFER)
00528   memset(&eglsrv, 0, sizeof(eglsrv));
00529 #endif
00530 #if defined(VMDGLXPBUFFER)
00531   memset(&glxsrv, 0, sizeof(glxsrv));
00532   glxsrv.dpy = NULL;
00533   glxsrv.dpyScreen = 0;
00534 #endif
00535 
00536   have_window = FALSE;
00537   screenX = screenY = 0;
00538 }
00539 
00540 
00541 int OpenGLPbufferDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
00542   vmdapp = app; 
00543                 
00544 
00545   
00546   
00547 
00548 #if defined(VMDGLXPBUFFER)
00549   int haveglxwin = 0;
00550   haveglxwin = glx_open_window(name, size, loc, argc, argv);
00551   if (haveglxwin)
00552     msgInfo << "Created GLX OpenGL Pbuffer for off-screen rendering" << sendmsg;
00553 #endif
00554 
00555 #if defined(VMDEGLPBUFFER)
00556   int haveeglwin = 0;
00557 #if defined(VMDGLXPBUFFER) 
00558   if (!haveglxwin)
00559 #endif
00560     haveeglwin = egl_open_window(name, size, loc, argc, argv);
00561 
00562   if (haveeglwin)
00563     msgInfo << "Created EGL OpenGL Pbuffer for off-screen rendering" << sendmsg;
00564 #endif
00565 
00566   if (!have_window) return FALSE;
00567 
00568   
00569   
00570   if (ext->hasmultisample) 
00571     aaAvailable = TRUE;  
00572   else
00573     aaAvailable = FALSE; 
00574 
00575   
00576   if (ext->hasmultisample) {
00577     aa_on();  
00578               
00579               
00580   } 
00581 
00582   cueingAvailable = TRUE;
00583   cueing_on(); 
00584 
00585   cullingAvailable = TRUE;
00586   culling_off();
00587 
00588   set_sphere_mode(sphereMode);
00589   set_sphere_res(sphereRes);
00590   set_line_width(lineWidth);
00591   set_line_style(lineStyle);
00592 
00593   
00594   reshape();
00595   normal();
00596   clear();
00597   update();
00598 
00599   
00600   return TRUE;
00601 }
00602 
00603 
00604 OpenGLPbufferDisplayDevice::~OpenGLPbufferDisplayDevice(void) {
00605   if (have_window) {
00606     free_opengl_ctx(); 
00607 
00608     
00609 #if defined(VMDEGLPBUFFER)
00610 #endif
00611 #if defined(VMDGLXPBUFFER)
00612     if (glxsrv.cx) {
00613       glXDestroyContext(glxsrv.dpy, glxsrv.cx);
00614       XCloseDisplay(glxsrv.dpy);
00615     }
00616 #endif
00617 
00618   }
00619 }
00620 
00621 
00623 
00624 
00625 #if defined(VMDEGLPBUFFER)
00626 
00627 
00628 static const char* vmd_get_egl_errorstring(void) {    
00629   EGLint errcode = eglGetError();
00630   switch (errcode) {
00631     case EGL_SUCCESS:              return "No error"; break;
00632     case EGL_NOT_INITIALIZED:      return "EGL not initialized"; break;
00633     case EGL_BAD_ACCESS:           return "EGL bad access"; break;
00634     case EGL_BAD_ALLOC:            return "EGL bad alloc"; break;
00635     case EGL_BAD_ATTRIBUTE:        return "EGL bad attribute"; break;
00636     case EGL_BAD_CONTEXT:          return "EGL bad context"; break;
00637     case EGL_BAD_CONFIG:           return "EGL bad config"; break;
00638     case EGL_BAD_CURRENT_SURFACE:  return "EGL bad cur context"; break;
00639     case EGL_BAD_DISPLAY:          return "EGL bad display"; break;
00640     case EGL_BAD_SURFACE:          return "EGL bad surface"; break;
00641     case EGL_BAD_MATCH:            return "EGL bad match"; break;
00642     case EGL_BAD_PARAMETER:        return "EGL bad parameter"; break;
00643     case EGL_BAD_NATIVE_PIXMAP:    return "EGL bad native pixmap"; break;
00644     case EGL_BAD_NATIVE_WINDOW:    return "EGL bad native window"; break;
00645     case EGL_CONTEXT_LOST:         return "EGL context lost"; break;
00646     default:
00647       return "Unrecognized EGL error"; break;
00648   }
00649 }
00650 
00651 
00652 
00653 int OpenGLPbufferDisplayDevice::egl_open_window(char *nm, int *size, int *loc,
00654                                                 int argc, char** argv) {
00655   
00656   eglsrv.dpy = EGL_NO_DISPLAY;
00657   eglsrv.numdevices = 0;
00658   eglsrv.devindex = 0;
00659 
00660 #if defined(EGL_EXT_platform_base) && (EGL_EGLEXT_VERSION >= 20160000)
00661   
00662   
00663   
00664 
00665   
00666   PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
00667   PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
00668   eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC) eglGetProcAddress("eglQueryDevicesEXT");     
00669   eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC) eglGetProcAddress("eglGetPlatformDisplayEXT");     
00670 
00671   
00672   if (eglQueryDevicesEXT != NULL && eglGetPlatformDisplayEXT != NULL) {
00673     static const int MAX_DEVICES = 16;
00674     EGLDeviceEXT devicelist[MAX_DEVICES];
00675     eglQueryDevicesEXT(MAX_DEVICES, devicelist, &eglsrv.numdevices);
00676 
00677     
00678     eglsrv.devindex = vmdapp->noderank % eglsrv.numdevices;
00679     eglsrv.dpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, devicelist[eglsrv.devindex], 0);
00680   }
00681 #endif
00682 
00683   
00684   if (eglsrv.dpy != EGL_NO_DISPLAY) {
00685     printf("Info) EGL: node[%d] bound to display[%d], %d %s total\n", 
00686             vmdapp->noderank, eglsrv.devindex, eglsrv.numdevices, 
00687             (eglsrv.numdevices == 1) ? "display" : "displays");
00688   } else {
00689     
00690     eglsrv.dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
00691   
00692     if (eglsrv.dpy != EGL_NO_DISPLAY)
00693       msgInfo << "EGL context bound to default display." << sendmsg;
00694   }
00695 
00696   
00697   if (eglsrv.dpy == EGL_NO_DISPLAY) {
00698     msgErr << "Exiting due to EGL Pbuffer creation failure." << sendmsg;
00699     return 0; 
00700   }
00701 
00702   EGLint eglmaj, eglmin;
00703   if (eglInitialize(eglsrv.dpy, &eglmaj, &eglmin) == EGL_FALSE) {
00704     msgErr << "Exiting due to EGL initialization failure." << sendmsg;
00705     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00706     return 0; 
00707   } 
00708   msgInfo << "EGL version " << eglmaj << "." << eglmin << sendmsg;
00709 
00710   int fbc = vmd_get_egl_fbconfig(&eglsrv, &ext->hasstereo, &ext->hasmultisample, &ext->nummultisamples);
00711   if (!fbc) {
00712     msgErr << "Exiting due to EGL config failure." << sendmsg;
00713     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00714     return 0; 
00715   }
00716 
00717   EGLint vid;
00718   if (eglGetConfigAttrib(eglsrv.dpy, eglsrv.conf, EGL_NATIVE_VISUAL_ID, &vid) == EGL_FALSE) {
00719     msgErr << "Exiting due to eglGetConfigAttrib() failure." << sendmsg;
00720     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00721     return 0; 
00722   }
00723 
00724   
00725   if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
00726     msgErr << "Exiting due to EGL OpenGL binding failure." << sendmsg;
00727     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00728     return 0; 
00729   }
00730 
00731   eglsrv.ctx = eglCreateContext(eglsrv.dpy, eglsrv.conf, EGL_NO_CONTEXT, NULL);
00732 
00733   
00734   static const EGLint pbuffer_fixedsz_attribs[] = {
00735     EGL_WIDTH, DEF_PBUFFER_XRES,
00736     EGL_HEIGHT, DEF_PBUFFER_YRES,
00737     EGL_NONE,
00738   };
00739 
00740   
00741   
00742   
00743   static const EGLint pbuffer_defsz_attribs[] = {
00744     EGL_WIDTH, DEF_PBUFFER_XRES,
00745     EGL_HEIGHT, DEF_PBUFFER_YRES,
00746     EGL_LARGEST_PBUFFER, EGL_TRUE,
00747     EGL_NONE,
00748   };
00749 
00750   
00751   static const EGLint pbuffer_maxsz_attribs[] = {
00752     EGL_WIDTH, 10000,
00753     EGL_HEIGHT, 10000,
00754     EGL_LARGEST_PBUFFER, EGL_TRUE,
00755     EGL_NONE,
00756   };
00757 
00758   
00759   
00760   static const EGLint pbuffer_hugesz_attribs[] = {
00761     EGL_WIDTH, 30000,
00762     EGL_HEIGHT, 30000,
00763     EGL_LARGEST_PBUFFER, EGL_TRUE,
00764     EGL_NONE,
00765   };
00766 
00767   EGLint const *pbuffer_attrs = pbuffer_defsz_attribs;
00768   if (getenv("VMDEGLUSEFIXEDSZ") != NULL) {
00769     pbuffer_attrs = pbuffer_fixedsz_attribs;
00770   }
00771   if (getenv("VMDEGLUSEMAXSZ") != NULL) {
00772     pbuffer_attrs = pbuffer_maxsz_attribs;
00773   }
00774   if (getenv("VMDEGLUSEHUGESZ") != NULL) {
00775     pbuffer_attrs = pbuffer_hugesz_attribs;
00776   }
00777 
00778   eglsrv.surf = eglCreatePbufferSurface(eglsrv.dpy, eglsrv.conf, pbuffer_attrs);
00779   if (eglsrv.surf == EGL_NO_SURFACE) {
00780     msgErr << "Exiting due to EGL Pbuffer surface creation failure." << sendmsg;
00781     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00782     return 0; 
00783   }
00784 
00785   EGLint surface_xsize, surface_ysize;
00786   if ((eglQuerySurface(eglsrv.dpy, eglsrv.surf, EGL_WIDTH, &surface_xsize) != EGL_TRUE) ||
00787       (eglQuerySurface(eglsrv.dpy, eglsrv.surf, EGL_HEIGHT, &surface_ysize) != EGL_TRUE)) {
00788     msgErr << "Exiting due to EGL Pbuffer surface dimensions query failure." << sendmsg;
00789     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00790     return 0; 
00791   }
00792 
00793   
00794   
00795   PbufferMaxXsz = surface_xsize;
00796   PbufferMaxYsz = surface_ysize;
00797 
00798   msgInfo << "OpenGL Pbuffer size: " 
00799           << PbufferMaxXsz << "x"
00800           << PbufferMaxYsz << sendmsg;
00801 
00802   
00803   xSize = size[0];
00804   ySize = size[1];
00805   if (xSize < 0 || xSize > PbufferMaxXsz || 
00806       ySize < 0 || ySize > PbufferMaxYsz) {
00807     msgWarn << "Ignored out-of-range OpenGL Pbuffer image dimension request: " 
00808             << xSize << "x" << ySize 
00809             << " (max: " 
00810             << PbufferMaxXsz << "x" << PbufferMaxYsz << ")" << sendmsg;
00811     xSize = PbufferMaxXsz;
00812     ySize = PbufferMaxYsz;
00813   }
00814 
00815   EGLBoolean ctxstatus = EGL_FALSE;
00816   ctxstatus = eglMakeCurrent(eglsrv.dpy, eglsrv.surf, eglsrv.surf, eglsrv.ctx);
00817   if (ctxstatus != EGL_TRUE) {
00818     msgErr << "Exiting due to EGL failure during eglMakeCurrent()." << sendmsg;
00819     msgErr << "  " << vmd_get_egl_errorstring() << sendmsg;
00820     return 0;
00821   }
00822 
00823 
00824   EGLint Context_RendererType=0;
00825   eglQueryContext(eglsrv.dpy, eglsrv.ctx, EGL_CONTEXT_CLIENT_TYPE, &Context_RendererType);
00826 
00827 #if 0
00828   const char *glstring="uninitialized";
00829   char buf[1024];
00830   switch (Context_RendererType) {
00831     case    EGL_OPENGL_API: glstring = "OpenGL"; break;
00832     case EGL_OPENGL_ES_API: glstring = "OpenGL ES"; break;
00833     case    EGL_OPENVG_API: glstring = "OpenVG???"; break;
00834     default:
00835       sprintf(buf, "Unknown API: %x", Context_RendererType);
00836       glstring=buf;
00837       break;
00838   }
00839   msgInfo << "EGL_CONTEXT_CLIENT_TYPE: %s\n", glstring);
00840 #endif
00841 
00842   
00843   
00844   if (ext->hasmultisample) {
00845     int msampeext = 0;
00846 
00847     
00848     if (ext->vmdQueryExtension("GL_ARB_multisample")) {
00849       msampeext = 1;
00850     }
00851 
00852     if (!msampeext) {
00853       ext->hasmultisample = FALSE;
00854       ext->nummultisamples = 0;
00855     }
00856   }
00857 
00858   
00859   setup_initial_opengl_state();  
00860 
00861   
00862   have_window = TRUE;
00863 
00864   return 1; 
00865 }
00866 #endif
00867 
00868 
00869 
00870 #if defined(VMDGLXPBUFFER)
00871 
00872 
00873 int OpenGLPbufferDisplayDevice::glx_open_window(char *nm, int *size, int *loc,
00874                                                 int argc, char** argv) {
00875   char *dispname;
00876   if ((dispname = getenv("VMDGDISPLAY")) == NULL)
00877     dispname = getenv("DISPLAY");
00878 
00879   if(!(glxsrv.dpy = XOpenDisplay(dispname))) {
00880     msgErr << "Exiting due to X-Windows GLX/OpenGL Pbuffer creation failure." << sendmsg;
00881     if (dispname != NULL) {
00882       msgErr << "Failed to open display: " << dispname << sendmsg;
00883     }
00884     return 0; 
00885   }
00886 
00887   
00888   
00889   
00890   glxsrv.dpyScreen = DefaultScreen(glxsrv.dpy);
00891   glxsrv.rootWindowID = RootWindow(glxsrv.dpy, glxsrv.dpyScreen);
00892   screenX = DisplayWidth(glxsrv.dpy, glxsrv.dpyScreen);
00893   screenY = DisplayHeight(glxsrv.dpy, glxsrv.dpyScreen);
00894 
00895   
00896   if (!glXQueryExtension(glxsrv.dpy, NULL, NULL)) {
00897     msgErr << "The X server does not support the OpenGL GLX extension." 
00898            << "   Exiting ..." << sendmsg;
00899     XCloseDisplay(glxsrv.dpy);
00900     return 0;
00901   }
00902 
00903   ext->hasstereo = TRUE;         
00904   ext->stereodrawforced = FALSE; 
00905   ext->hasmultisample = TRUE;    
00906 
00907   
00908   GLXFBConfig *fbc;
00909   fbc = vmd_get_glx_fbconfig(&glxsrv, &ext->hasstereo, &ext->hasmultisample, &ext->nummultisamples);
00910   if (fbc == NULL) {
00911     msgErr << "No OpenGL Pbuffer configurations available" << sendmsg;
00912     return 0;
00913   }
00914 
00915   
00916   const int pbconf[] = {GLX_PBUFFER_WIDTH, DEF_PBUFFER_XRES, 
00917                         GLX_PBUFFER_HEIGHT, DEF_PBUFFER_YRES,
00918                         GLX_LARGEST_PBUFFER, 1,
00919                         GLX_PRESERVED_CONTENTS, 1, 
00920                         None};
00921   GLXPbuffer PBuffer = glXCreatePbuffer(glxsrv.dpy, fbc[0], pbconf);
00922   glxsrv.cx = glXCreateNewContext(glxsrv.dpy, fbc[0], GLX_RGBA_TYPE, 0, GL_TRUE);
00923   if (PBuffer == 0 || glxsrv.cx == NULL) {
00924     msgErr << "A TrueColor OpenGL Pbuffer is required, but not available." << sendmsg;
00925     msgErr << "The X server is not capable of displaying double-buffered," << sendmsg;
00926     msgErr << "RGB images with a Z buffer.   Exiting ..." << sendmsg;
00927     XCloseDisplay(glxsrv.dpy);
00928     return 0;
00929   }
00930 
00931   
00932   
00933   PbufferMaxXsz = DEF_PBUFFER_XRES;
00934   PbufferMaxYsz = DEF_PBUFFER_YRES;
00935   glXQueryDrawable(glxsrv.dpy, PBuffer, GLX_WIDTH,  &PbufferMaxXsz);
00936   glXQueryDrawable(glxsrv.dpy, PBuffer, GLX_HEIGHT, &PbufferMaxYsz);
00937 
00938   msgInfo << "OpenGL Pbuffer size: " 
00939           << PbufferMaxXsz << "x"
00940           << PbufferMaxYsz << sendmsg;
00941 
00942   
00943   xSize = size[0];
00944   ySize = size[1];
00945   if (xSize < 0 || xSize > PbufferMaxXsz || 
00946       ySize < 0 || ySize > PbufferMaxYsz) {
00947     msgWarn << "Ignored out-of-range OpenGL Pbuffer image dimension request: " 
00948             << xSize << "x" << ySize 
00949             << " (max: " 
00950             << PbufferMaxXsz << "x" << PbufferMaxYsz << ")" << sendmsg;
00951     xSize = PbufferMaxXsz;
00952     ySize = PbufferMaxYsz;
00953   }
00954 
00955   
00956   glXMakeContextCurrent(glxsrv.dpy, PBuffer, PBuffer, glxsrv.cx);
00957   glXMakeCurrent(glxsrv.dpy, PBuffer, glxsrv.cx);
00958 
00959   
00960   
00961   if (ext->hasmultisample) {
00962     int msampeext = 0;
00963 
00964     
00965     if (ext->vmdQueryExtension("GL_ARB_multisample")) {
00966       msampeext = 1;
00967     }
00968 
00969     if (!msampeext) {
00970       ext->hasmultisample = FALSE;
00971       ext->nummultisamples = 0;
00972     }
00973   }
00974 
00975   
00976   setup_initial_opengl_state();  
00977 
00978   
00979   have_window = TRUE;
00980 
00981   
00982   glxsrv.windowID = PBuffer;
00983 
00984   return 1; 
00985 }
00986 #endif
00987 
00988 
00990 
00991 
00992 
00993 
00994 void OpenGLPbufferDisplayDevice::do_resize_window(int w, int h) {
00995   if ((w > 0) && (w <= ((int) PbufferMaxXsz))) {
00996     xSize = w;
00997   } else {
00998     msgWarn << "Ignored out-of-range OpenGL Pbuffer X dimension request: " 
00999             << w << " (max: " << PbufferMaxXsz << ")" << sendmsg;
01000   }
01001   if ((h > 0) && (h <= ((int) PbufferMaxYsz))) {
01002     ySize = h;
01003   } else {
01004     msgWarn << "Ignored out-of-range OpenGL Pbuffer Y dimension request: " 
01005             << h << " (max: " << PbufferMaxYsz << ")" << sendmsg;
01006   }
01007 
01008   
01009   reshape();
01010 
01011   
01012   _needRedraw = 1;
01013 }
01014 
01015 
01016 
01017 void OpenGLPbufferDisplayDevice::reshape(void) {
01018   switch (inStereo) {
01019     case OPENGL_STEREO_SIDE:
01020       set_screen_pos(0.5f * (float)xSize / (float)ySize);
01021       break;
01022 
01023     case OPENGL_STEREO_ABOVEBELOW:
01024       set_screen_pos(2.0f * (float)xSize / (float)ySize);
01025       break;
01026 
01027     case OPENGL_STEREO_STENCIL_CHECKERBOARD:
01028     case OPENGL_STEREO_STENCIL_COLUMNS:
01029     case OPENGL_STEREO_STENCIL_ROWS:
01030       enable_stencil_stereo(inStereo);
01031       set_screen_pos((float)xSize / (float)ySize);
01032       break;
01033  
01034     default:
01035       set_screen_pos((float)xSize / (float)ySize);
01036       break;
01037   }
01038 }
01039 
01040 
01041 unsigned char * OpenGLPbufferDisplayDevice::readpixels_rgb3u(int &xs, int &ys) {
01042   unsigned char * img = NULL;
01043   xs = xSize;
01044   ys = ySize;
01045 
01046   
01047   if ((img = (unsigned char *) malloc(xs * ys * 3)) != NULL) {
01048     glPixelStorei(GL_PACK_ALIGNMENT, 1);
01049     glReadPixels(0, 0, xs, ys, GL_RGB, GL_UNSIGNED_BYTE, img);
01050     return img; 
01051   }
01052 
01053   
01054   xs = 0;
01055   ys = 0;
01056   return NULL;
01057 }
01058 
01059 unsigned char * OpenGLPbufferDisplayDevice::readpixels_rgba4u(int &xs, int &ys) {
01060   unsigned char * img = NULL;
01061   xs = xSize;
01062   ys = ySize;
01063 
01064   
01065   if ((img = (unsigned char *) malloc(xs * ys * 4)) != NULL) {
01066     glPixelStorei(GL_PACK_ALIGNMENT, 1);
01067     glReadPixels(0, 0, xs, ys, GL_RGBA, GL_UNSIGNED_BYTE, img);
01068     return img; 
01069   }
01070 
01071   
01072   xs = 0;
01073   ys = 0;
01074   return NULL;
01075 }
01076 
01077 
01078 
01079 void OpenGLPbufferDisplayDevice::update(int do_update) {
01080   if (wiregl) {
01081     glFinish(); 
01082                 
01083                 
01084   }
01085 
01086 #if 1
01087   
01088   
01089   if (vmdapp->uivs && vmdapp->uivs->srv_connected()) {
01090     
01091     int xs, ys;
01092     unsigned char *img = NULL;
01093     img = readpixels_rgba4u(xs, ys);
01094     if (img != NULL) {
01095       
01096       vmdapp->uivs->video_frame_pending(img, xs, ys);
01097       vmdapp->uivs->check_event();
01098       free(img);
01099     }
01100   }
01101 #endif
01102 
01103 #if defined(VMDEGLPBUFFER)
01104 #if 1
01105   if (do_update)
01106     eglSwapBuffers(eglsrv.dpy, eglsrv.surf);
01107 #else
01108   EGLBoolean eglrc = EGL_TRUE;
01109   if (do_update)
01110     eglrc = eglSwapBuffers(eglsrv.dpy, eglsrv.surf);
01111 
01112   if (eglrc != EGL_TRUE) {
01113     printf("eglSwapBuffers(): EGLrc: %d\n", eglrc);
01114   }
01115 #endif
01116 #endif
01117 
01118 #if defined(VMDGLXPBUFFER)
01119   if (do_update)
01120     glXSwapBuffers(glxsrv.dpy, glxsrv.windowID);
01121 #endif
01122 
01123   glDrawBuffer(GL_BACK);
01124 }
01125