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