00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00024 #include <stdlib.h>
00025 #include <math.h>
00026 #include <GL/gl.h>
00027 #include <GL/glx.h>
00028 #include <X11/Xlib.h>
00029 #include <X11/cursorfont.h>
00030 #include <X11/keysym.h>
00031
00032 #if defined(VMDXINERAMA)
00033 #include <X11/extensions/Xinerama.h>
00034 #endif
00035
00036 #include "OpenGLDisplayDevice.h"
00037 #include "Inform.h"
00038 #include "utilities.h"
00039 #include "config.h"
00040
00041 #include "VMDApp.h"
00042 #include "VideoStream.h"
00043
00044 #if defined(VMDOPTIXRTRT)
00045 #include "OptiXRenderer.h"
00046 #endif
00047
00048
00049
00050 static const char *glStereoNameStr[OPENGL_STEREO_MODES] =
00051 { "Off",
00052 "QuadBuffered",
00053 "HDTV SideBySide",
00054 "Checkerboard",
00055 "ColumnInterleaved",
00056 "RowInterleaved",
00057 "Anaglyph",
00058 "SideBySide",
00059 "AboveBelow",
00060 "Left",
00061 "Right" };
00062
00063 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00064 { "Normal",
00065 "GLSL",
00066 #if defined(VMDOPTIXRTRT)
00067 "Tachyon RTX RTRT",
00068 #endif
00069 "Acrobat3D" };
00070
00071 static const char *glCacheNameStr[OPENGL_CACHE_MODES] =
00072 { "Off",
00073 "On" };
00074
00075
00076 #if defined(GL_ARB_multisample) && defined(GLX_SAMPLES_ARB) && defined(GLX_SAMPLE_BUFFERS_ARB)
00077 #define USEARBMULTISAMPLE 1
00078 #endif
00079
00080
00081 static XColor cursorFG = { 0, 0xffff, 0, 0,
00082 DoRed | DoGreen | DoBlue, 0 };
00083 static XColor cursorBG = { 0, 0xffff, 0xffff, 0xffff,
00084 DoRed | DoGreen | DoBlue, 0 };
00085
00087
00088 #if defined(VMDXINPUT)
00089 #include <X11/extensions/XI.h>
00090 #include <X11/extensions/XInput.h>
00091
00092 typedef struct {
00093 XDevice *dev;
00094 int motionevent;
00095 int motioneventclass;
00096 int buttonpressevent;
00097 int buttonpresseventclass;
00098 int buttonreleaseevent;
00099 int buttonreleaseeventclass;
00100 XEventClass evclasses[3];
00101 } xidevhandle;
00102
00103 typedef struct {
00104 Display *dpy;
00105 Window win;
00106 xidevhandle *dev_spaceball;
00107 xidevhandle *dev_dialbox;
00108 } xinputhandle;
00109
00110
00111 static xidevhandle * xinput_open_device(xinputhandle *handle, XID devinfo) {
00112 xidevhandle *xdhandle = (xidevhandle *) malloc(sizeof(xidevhandle));
00113 memset(xdhandle, 0, sizeof(xidevhandle));
00114 xdhandle->dev = XOpenDevice(handle->dpy, devinfo);
00115 if (xdhandle->dev == NULL) {
00116 free(xdhandle);
00117 return NULL;
00118 }
00119
00120 DeviceMotionNotify(xdhandle->dev, xdhandle->motionevent, xdhandle->motioneventclass);
00121 DeviceButtonPress(xdhandle->dev, xdhandle->buttonpressevent, xdhandle->buttonpresseventclass);
00122 DeviceButtonRelease(xdhandle->dev, xdhandle->buttonreleaseevent, xdhandle->buttonreleaseeventclass);
00123
00124 xdhandle->evclasses[0] = xdhandle->motioneventclass;
00125 xdhandle->evclasses[1] = xdhandle->buttonpresseventclass;
00126 xdhandle->evclasses[2] = xdhandle->buttonreleaseeventclass;
00127
00128 XSelectExtensionEvent(handle->dpy, handle->win, xdhandle->evclasses, 3);
00129
00130 return xdhandle;
00131 }
00132
00133
00134 static void xinput_close_device(xinputhandle *handle, xidevhandle *xdhandle) {
00135 if (handle == NULL || xdhandle == NULL)
00136 return;
00137
00138 if (xdhandle->dev != NULL) {
00139 XCloseDevice(handle->dpy, xdhandle->dev);
00140 }
00141 free(xdhandle);
00142 }
00143
00144
00145 static int xinput_device_decode_event(xinputhandle *handle, xidevhandle *dev,
00146 XEvent *xev, spaceballevent *sballevent) {
00147 if (xev->type == dev->motionevent) {
00148 XDeviceMotionEvent *mptr = (XDeviceMotionEvent *) xev;
00149
00150
00151
00152
00153
00154 sballevent->tx += mptr->axis_data[0];
00155 sballevent->ty += mptr->axis_data[1];
00156 sballevent->tz += mptr->axis_data[2];
00157 sballevent->rx += mptr->axis_data[3];
00158 sballevent->ry += mptr->axis_data[4];
00159 sballevent->rz += mptr->axis_data[5];
00160 sballevent->period += 50;
00161 sballevent->event = 1;
00162 return 1;
00163 } else if (xev->type == dev->buttonpressevent) {
00164
00165
00166 sballevent->buttons |= 1;
00167 sballevent->event = 1;
00168 return 1;
00169 } else if (xev->type == dev->buttonreleaseevent) {
00170
00171
00172 sballevent->buttons &= ~1;
00173 sballevent->event = 1;
00174 return 1;
00175 }
00176
00177 return 0;
00178 }
00179
00180
00181 static int xinput_decode_event(xinputhandle *handle, XEvent *xev,
00182 spaceballevent *sballevent) {
00183 if (handle == NULL)
00184 return 0;
00185
00186 if (handle->dev_spaceball != NULL) {
00187 return xinput_device_decode_event(handle, handle->dev_spaceball, xev, sballevent);
00188 }
00189
00190 return 0;
00191 }
00192
00193
00194
00195 static xinputhandle * xinput_enable(Display *dpy, Window win) {
00196 xinputhandle *handle = NULL;
00197 int i, numdev, numextdev;
00198 XDeviceInfoPtr list;
00199 int ximajor, xiev, xierr;
00200 Atom sballdevtype;
00201
00202 xidevhandle *dev_spaceball = NULL;
00203
00204
00205
00206 if(!XQueryExtension(dpy,"XInputExtension", &ximajor, &xiev, &xierr)) {
00207 msgInfo << "X-Windows XInput extension unavailable." << sendmsg;
00208 return NULL;
00209 }
00210
00211 sballdevtype = XInternAtom(dpy, XI_SPACEBALL, True);
00212
00213
00214
00215 list = (XDeviceInfoPtr) XListInputDevices(dpy, &numdev);
00216
00217 numextdev = 0;
00218 for (i = 0; i < numdev; i++) {
00219 if (list[i].use == IsXExtensionDevice) {
00220
00221 if (!strupncmp(list[i].name, "evdev brain", strlen("evdev brain")))
00222 continue;
00223
00224 numextdev++;
00225 }
00226 }
00227
00228 if (numextdev > 0) {
00229 handle = (xinputhandle *) malloc(sizeof(xinputhandle));
00230 memset(handle, 0, sizeof(xinputhandle));
00231 handle->dpy = dpy;
00232 handle->win = win;
00233
00234 msgInfo << "Detected " << numdev << " XInput devices, "
00235 << numextdev << " usable device"
00236 << ((numextdev > 1) ? "s:" : ":") << sendmsg;
00237
00238 for (i = 0; i < numdev; i++) {
00239 if (list[i].use == IsXExtensionDevice) {
00240
00241 if (!strupncmp(list[i].name, "evdev brain", strlen("evdev brain")))
00242 continue;
00243
00244
00245 msgInfo << " [" << list[i].id << "] " << list[i].name
00246 << ", type: " << (int) list[i].type
00247 << ", classes: " << (int) list[i].num_classes << sendmsg;
00248
00249
00250 if ((dev_spaceball == NULL) &&
00251 (((sballdevtype != None) && (list[i].type == sballdevtype)) ||
00252 !strupncmp(list[i].name, "SPACEBALL", strlen("SPACEBALL")) ||
00253 !strupncmp(list[i].name, "MAGELLAN", strlen("MAGELLAN")))) {
00254 dev_spaceball = xinput_open_device(handle, list[i].id);
00255 }
00256
00257 #if 0
00258
00259 if ((dev_dialbox == NULL) &&
00260 ((dialboxdevtype != None) && (list[i].type == dialboxdevtype))) {
00261 dev_dialbox = xinput_open_device(handle, list[i].id);
00262 }
00263 #endif
00264 }
00265 }
00266 XFreeDeviceList(list);
00267 } else {
00268
00269 XFreeDeviceList(list);
00270 return NULL;
00271 }
00272
00273 if (dev_spaceball) {
00274 msgInfo << "Attached to XInput Spaceball" << sendmsg;
00275 }
00276
00277
00278
00279
00280 if (dev_spaceball != NULL ) {
00281 handle->dev_spaceball = dev_spaceball;
00282
00283 } else {
00284 free(handle);
00285 return NULL;
00286 }
00287
00288 return handle;
00289 }
00290
00291 void xinput_close(xinputhandle *handle) {
00292 if (handle != NULL) {
00293 xinput_close_device(handle, handle->dev_spaceball);
00294
00295 free(handle);
00296 }
00297 }
00298
00299 #endif
00300
00301
00302
00303 static spaceballhandle * spaceball_enable(Display *dpy, Window win) {
00304
00305 spaceballhandle *handle = (spaceballhandle *) malloc(sizeof(spaceballhandle));
00306 memset(handle, 0, sizeof(spaceballhandle));
00307
00308
00309 handle->ev_motion = XInternAtom(dpy, "MotionEvent", True);
00310 handle->ev_button_press = XInternAtom(dpy, "ButtonPressEvent", True);
00311 handle->ev_button_release = XInternAtom(dpy, "ButtonReleaseEvent", True);
00312 handle->ev_command = XInternAtom(dpy, "CommandEvent", True);
00313
00314 if (!handle->ev_motion || !handle->ev_button_press ||
00315 !handle->ev_button_release || !handle->ev_command) {
00316 free(handle);
00317 return NULL;
00318 }
00319
00320
00321 Window root = RootWindow(dpy, DefaultScreen(dpy));
00322
00323
00324 Atom ActualType;
00325 int ActualFormat;
00326 unsigned long NItems, BytesReturn;
00327 unsigned char *PropReturn = NULL;
00328 XGetWindowProperty(dpy, root, handle->ev_command, 0, 1, FALSE,
00329 AnyPropertyType, &ActualType, &ActualFormat, &NItems,
00330 &BytesReturn, &PropReturn );
00331 if (PropReturn == NULL) {
00332 free(handle);
00333 return NULL;
00334 }
00335 handle->drv_win = *(Window *) PropReturn;
00336 XFree(PropReturn);
00337
00338 XTextProperty sball_drv_winname;
00339 if (XGetWMName(dpy, handle->drv_win, &sball_drv_winname) != 0) {
00340 if (!strcmp("Magellan Window", (char *) sball_drv_winname.value)) {
00341
00342 XEvent msg;
00343 msg.type = ClientMessage;
00344 msg.xclient.format = 16;
00345 msg.xclient.send_event = FALSE;
00346 msg.xclient.display = dpy;
00347 msg.xclient.window = handle->drv_win;
00348 msg.xclient.message_type = handle->ev_command;
00349
00350 msg.xclient.data.s[0] = (short) (((win)>>16)&0x0000FFFF);
00351 msg.xclient.data.s[1] = (short) (((win)) &0x0000FFFF);
00352 msg.xclient.data.s[2] = SBALL_COMMAND_APP_WINDOW;
00353
00354 int rc = XSendEvent(dpy, handle->drv_win, FALSE, 0x0000, &msg);
00355 XFlush(dpy);
00356 if (rc == 0) {
00357 free(handle);
00358 return NULL;
00359 }
00360 }
00361
00362 XFree(sball_drv_winname.value);
00363 }
00364
00365 return handle;
00366 }
00367
00368
00369 static void spaceball_close(spaceballhandle *handle) {
00370 free(handle);
00371 }
00372
00373
00374 static int spaceball_decode_event(spaceballhandle *handle, const XEvent *xev, spaceballevent *sballevent) {
00375 unsigned int evtype;
00376
00377 if (handle == NULL || xev == NULL || sballevent == NULL)
00378 return 0;
00379
00380 if (xev->type != ClientMessage)
00381 return 0;
00382
00383 evtype = xev->xclient.message_type;
00384
00385 if (evtype == handle->ev_motion) {
00386
00387
00388
00389
00390 sballevent->tx += xev->xclient.data.s[2];
00391 sballevent->ty += xev->xclient.data.s[3];
00392 sballevent->tz += xev->xclient.data.s[4];
00393 sballevent->rx += xev->xclient.data.s[5];
00394 sballevent->ry += xev->xclient.data.s[6];
00395 sballevent->rz += xev->xclient.data.s[7];
00396 sballevent->period += xev->xclient.data.s[8];
00397 sballevent->event = 1;
00398 return 1;
00399 } else if (evtype == handle->ev_button_press) {
00400
00401
00402 sballevent->buttons |= (1 << xev->xclient.data.s[2]);
00403 sballevent->event = 1;
00404 return 1;
00405 } else if (evtype == handle->ev_button_release) {
00406
00407
00408 sballevent->buttons &= ~(1 << xev->xclient.data.s[2]);
00409 sballevent->event = 1;
00410 return 1;
00411 }
00412
00413 return 0;
00414 }
00415
00416
00417 static void spaceball_init_event(spaceballevent *sballevent) {
00418 memset(sballevent, 0, sizeof(spaceballevent));
00419 }
00420
00421
00422 static void spaceball_clear_event(spaceballevent *sballevent) {
00423 sballevent->tx = 0;
00424 sballevent->ty = 0;
00425 sballevent->tz = 0;
00426 sballevent->rx = 0;
00427 sballevent->ry = 0;
00428 sballevent->rz = 0;
00429 sballevent->period = 0;
00430 sballevent->event = 0;
00431 }
00432
00433
00434 static XVisualInfo * vmd_get_visual(glxdata *glxsrv, int *stereo, int *msamp, int *numsamples) {
00435
00436 XVisualInfo *vi;
00437 int ns, dsize;
00438 int simplegraphics = 0;
00439 int disablestereo = 0;
00440 vi = NULL;
00441 *numsamples = 0;
00442 *msamp = FALSE;
00443 *stereo = FALSE;
00444
00445 if (getenv("VMDSIMPLEGRAPHICS")) {
00446 simplegraphics = 1;
00447 }
00448
00449 if (getenv("VMDDISABLESTEREO")) {
00450 disablestereo = 1;
00451 }
00452
00453
00454 int maxaasamples=4;
00455 const char *maxaasamplestr = getenv("VMDMAXAASAMPLES");
00456 if (maxaasamplestr) {
00457 int aatmp;
00458 if (sscanf(maxaasamplestr, "%d", &aatmp) == 1) {
00459 if (aatmp >= 0) {
00460 maxaasamples=aatmp;
00461 msgInfo << "User-requested OpenGL antialiasing sample depth: "
00462 << maxaasamples << sendmsg;
00463
00464 if (maxaasamples < 2) {
00465 maxaasamples=1;
00466 msgInfo << "OpenGL antialiasing disabled by user override."
00467 << sendmsg;
00468 }
00469 } else {
00470 msgErr << "Ignoring user-requested OpenGL antialiasing sample depth: "
00471 << aatmp << sendmsg;
00472 }
00473 } else {
00474 msgErr << "Unable to parse override of OpenGL antialiasing" << sendmsg;
00475 msgErr << "sample depth: '" << maxaasamplestr << "'" << sendmsg;
00476 }
00477 }
00478
00479
00480
00481
00482 for (dsize=32; dsize >= 16; dsize-=4) {
00483
00484
00485 #if defined(USEARBMULTISAMPLE)
00486 if (!simplegraphics && !disablestereo && (!vi || (vi->c_class != TrueColor))) {
00487
00488 for (ns=maxaasamples; ns>1; ns--) {
00489 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, dsize,
00490 GLX_STEREO,
00491 GLX_STENCIL_SIZE, 1,
00492 GLX_SAMPLE_BUFFERS_ARB, 1, GLX_SAMPLES_ARB, ns, None};
00493 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00494
00495 if (vi && (vi->c_class == TrueColor)) {
00496 *numsamples = ns;
00497 *msamp = TRUE;
00498 *stereo = TRUE;
00499 break;
00500 }
00501 }
00502 }
00503 #endif
00504
00505 if (getenv("VMDPREFERSTEREO") != NULL && !disablestereo) {
00506
00507
00508
00509
00510
00511 if (!simplegraphics && (!vi || (vi->c_class != TrueColor))) {
00512 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, dsize,
00513 GLX_STEREO,
00514 GLX_STENCIL_SIZE, 1,
00515 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None};
00516 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00517 ns = 0;
00518 *numsamples = ns;
00519 *msamp = FALSE;
00520 *stereo = TRUE;
00521 }
00522 }
00523 #if defined(USEARBMULTISAMPLE)
00524 else {
00525
00526 if (!simplegraphics && (!vi || (vi->c_class != TrueColor))) {
00527
00528 for (ns=maxaasamples; ns>1; ns--) {
00529 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, dsize,
00530 GLX_STENCIL_SIZE, 1,
00531 GLX_SAMPLE_BUFFERS_ARB, 1, GLX_SAMPLES_ARB, ns, None};
00532 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00533
00534 if (vi && (vi->c_class == TrueColor)) {
00535 *numsamples = ns;
00536 *msamp = TRUE;
00537 *stereo = FALSE;
00538 break;
00539 }
00540 }
00541 }
00542 }
00543 #endif
00544
00545 }
00546
00547
00548
00549
00550
00551
00552 if (!simplegraphics && !disablestereo && (!vi || (vi->c_class != TrueColor))) {
00553 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_STEREO,
00554 GLX_STENCIL_SIZE, 1,
00555 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None};
00556 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00557 ns = 0;
00558 *numsamples = ns;
00559 *msamp = FALSE;
00560 *stereo = TRUE;
00561 }
00562
00563
00564 if (!simplegraphics && !disablestereo && (!vi || (vi->c_class != TrueColor))) {
00565 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_STEREO,
00566 GLX_STENCIL_SIZE, 1,
00567 GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
00568 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00569 ns = 0;
00570 *numsamples = ns;
00571 *msamp = FALSE;
00572 *stereo = TRUE;
00573 }
00574
00575
00576
00577
00578
00579 if (!simplegraphics && !disablestereo && (!vi || (vi->c_class != TrueColor))) {
00580 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, GLX_STEREO,
00581 GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
00582 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00583 ns = 0;
00584 *numsamples = ns;
00585 *msamp = FALSE;
00586 *stereo = TRUE;
00587 }
00588
00589
00590
00591 if (!simplegraphics && (!vi || (vi->c_class != TrueColor))) {
00592 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16,
00593 GLX_STENCIL_SIZE, 1,
00594 GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, None};
00595 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00596 ns = 0;
00597 *numsamples = ns;
00598 *msamp = FALSE;
00599 *stereo = FALSE;
00600 }
00601
00602
00603 if(!vi || (vi->c_class != TrueColor)) {
00604
00605
00606
00607
00608 int conf[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16,
00609 GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None};
00610 vi = glXChooseVisual(glxsrv->dpy, glxsrv->dpyScreen, conf);
00611 ns = 0;
00612 *numsamples = ns;
00613 *msamp = FALSE;
00614 *stereo = FALSE;
00615 }
00616
00617 if (!vi || (vi->c_class != TrueColor)) {
00618
00619 ns = 0;
00620 *numsamples = ns;
00621 *msamp = FALSE;
00622 *stereo = FALSE;
00623 }
00624
00625 return vi;
00626 }
00627
00628
00629
00630 static void setfullscreen(int fson, Display *dpy, Window win, int xinescreen) {
00631 struct {
00632 unsigned long flags;
00633 unsigned long functions;
00634 unsigned long decorations;
00635 long inputMode;
00636 unsigned long status;
00637 } wmhints;
00638
00639 memset(&wmhints, 0, sizeof(wmhints));
00640 wmhints.flags = 2;
00641 if (fson) {
00642 wmhints.decorations = 0;
00643 } else {
00644 wmhints.decorations = 1;
00645 }
00646
00647 #if !defined(VMD_NANOHUB)
00648 Atom wmproperty = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);
00649 #else
00650
00651 Atom wmproperty = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
00652 #endif
00653 XChangeProperty(dpy, win, wmproperty, wmproperty, 32,
00654 PropModeReplace, (unsigned char *) &wmhints, 5);
00655
00656
00657
00658
00659 if (fson) {
00660 int dpyScreen = DefaultScreen(dpy);
00661
00662 XSizeHints sizeHints;
00663 memset((void *) &(sizeHints), 0, sizeof(sizeHints));
00664 sizeHints.flags |= USSize;
00665 sizeHints.flags |= USPosition;
00666
00667 sizeHints.width = DisplayWidth(dpy, dpyScreen);
00668 sizeHints.height = DisplayHeight(dpy, dpyScreen);
00669 sizeHints.x = 0;
00670 sizeHints.y = 0;
00671
00672 #if defined(VMDXINERAMA)
00673 if (xinescreen != -1) {
00674 int xinerr, xinevent, xinenumscreens;
00675 if (XineramaQueryExtension(dpy, &xinevent, &xinerr) &&
00676 XineramaIsActive(dpy)) {
00677 XineramaScreenInfo *screens =
00678 XineramaQueryScreens(dpy, &xinenumscreens);
00679 if (xinescreen >= 0 && xinescreen < xinenumscreens) {
00680 sizeHints.width = screens[xinescreen].width;
00681 sizeHints.height = screens[xinescreen].height;
00682 sizeHints.x = screens[xinescreen].x_org;
00683 sizeHints.y = screens[xinescreen].y_org;
00684 }
00685 XFree(screens);
00686 }
00687 }
00688 #endif
00689
00690 XMoveWindow(dpy, win, sizeHints.x, sizeHints.y);
00691 XResizeWindow(dpy, win, sizeHints.width, sizeHints.height);
00692 }
00693 }
00694
00695
00697
00698 OpenGLDisplayDevice::OpenGLDisplayDevice()
00699 : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {
00700
00701
00702 stereoNames = glStereoNameStr;
00703 stereoModes = OPENGL_STEREO_MODES;
00704
00705 renderNames = glRenderNameStr;
00706 renderModes = OPENGL_RENDER_MODES;
00707
00708 cacheNames = glCacheNameStr;
00709 cacheModes = OPENGL_CACHE_MODES;
00710
00711 memset(&glxsrv, 0, sizeof(glxsrv));
00712 glxsrv.dpy = NULL;
00713 glxsrv.dpyScreen = 0;
00714 glxsrv.xinp = NULL;
00715 glxsrv.sball = NULL;
00716 glxsrv.havefocus = 0;
00717 have_window = FALSE;
00718 screenX = screenY = 0;
00719
00720 #if defined(VMDOPTIXRTRT)
00721 ort = NULL;
00722 ogl_optix_rtrt_passthrough = 0;
00723 #endif
00724
00725 }
00726
00727 int OpenGLDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
00728 vmdapp = app;
00729
00730
00731
00732 glxsrv.windowID = open_window(name, size, loc, argc, argv);
00733 if (!have_window) return FALSE;
00734
00735
00736
00737 if (ext->hasmultisample)
00738 aaAvailable = TRUE;
00739 else
00740 aaAvailable = FALSE;
00741
00742
00743 if (ext->hasmultisample) {
00744 aa_on();
00745
00746
00747 }
00748
00749 cueingAvailable = TRUE;
00750 cueing_on();
00751
00752 cullingAvailable = TRUE;
00753 culling_off();
00754
00755 set_sphere_mode(sphereMode);
00756 set_sphere_res(sphereRes);
00757 set_line_width(lineWidth);
00758 set_line_style(lineStyle);
00759
00760
00761 reshape();
00762 normal();
00763 clear();
00764 update();
00765
00766 #if defined(VMDOPTIXRTRT)
00767 printf("OpenGLDisplayDevice) Creating OptiX RTRT context...\n");
00768 ort = new OptiXRenderer(vmdapp);
00769 if (ort != NULL) {
00770 int i;
00771
00772 ort->setup_context(xSize, ySize);
00773
00774
00775
00776 ort->destroy_scene();
00777
00778
00779 ort->set_bg_mode(OptiXRenderer::RT_BACKGROUND_TEXTURE_SOLID);
00780 ort->shadows_on(shadows_enabled());
00781 ort->set_aa_samples(8);
00782 ort->set_ao_samples(ao_enabled());
00783 ort->set_ao_ambient(get_ao_ambient());
00784 ort->set_ao_direct(get_ao_direct());
00785 ort->dof_on(dof_enabled());
00786 ort->set_camera_dof_fnumber(get_dof_fnumber());
00787 ort->set_camera_dof_focal_dist(get_dof_focal_dist());
00788
00789 ort->set_cue_mode(OptiXRenderer::RT_FOG_NONE,
00790 get_cue_start(), get_cue_end(), get_cue_density());
00791
00792 ort->set_camera_projection(OptiXRenderer::RT_PERSPECTIVE);
00793 ort->set_camera_zoom(0.5f / ((eyePos[2] - zDist) / vSize));
00794
00795
00796 ort->set_camera_stereo_eyesep(eyeSep);
00797 ort->set_camera_stereo_convergence_dist(eyeDist);
00798
00799
00800
00801 ort->clear_all_lights();
00802
00803
00804 for (i=0; i<DISP_LIGHTS; i++) {
00805 if (ogl_lightstate[i]) {
00806 ort->add_directional_light(ogl_lightpos[i], ogl_lightcolor[i]);
00807 }
00808 }
00809
00810
00811 }
00812
00813 printf("OpenGLDisplayDevice) OptiX RTRT context created.\n");
00814 #endif
00815
00816
00817 return TRUE;
00818 }
00819
00820
00821 OpenGLDisplayDevice::~OpenGLDisplayDevice(void) {
00822 #if defined(VMDOPTIXRTRT)
00823 printf("OpenGLDisplayDevice) Destroying OptiX RTRT context...\n");
00824 delete ort;
00825 ort = NULL;
00826 printf("OpenGLDisplayDevice) OptiX RTRT context destroyed.\n");
00827 #endif
00828
00829 if (have_window) {
00830 #if defined(VMDXINPUT)
00831
00832 if (glxsrv.xinp != NULL) {
00833 xinput_close((xinputhandle *) glxsrv.xinp);
00834 }
00835 #endif
00836
00837
00838 if (glxsrv.sball != NULL) {
00839 spaceball_close(glxsrv.sball);
00840 }
00841
00842 free_opengl_ctx();
00843
00844
00845 XUnmapWindow(glxsrv.dpy, glxsrv.windowID);
00846 glXDestroyContext(glxsrv.dpy, glxsrv.cx);
00847 XDestroyWindow(glxsrv.dpy, glxsrv.windowID);
00848 XCloseDisplay(glxsrv.dpy);
00849 }
00850 }
00851
00852
00854
00855
00856
00857 Window OpenGLDisplayDevice::open_window(char *nm, int *size, int *loc,
00858 int argc, char** argv
00859 ) {
00860 Window win;
00861 int i, SX = 100, SY = 100, W, H;
00862
00863 char *dispname;
00864 if ((dispname = getenv("VMDGDISPLAY")) == NULL)
00865 dispname = getenv("DISPLAY");
00866
00867 if(!(glxsrv.dpy = XOpenDisplay(dispname))) {
00868 msgErr << "Exiting due to X-Windows OpenGL window creation failure." << sendmsg;
00869 if (dispname != NULL) {
00870 msgErr << "Failed to open display: " << dispname << sendmsg;
00871 }
00872 return (Window)0;
00873 }
00874
00875
00876 #if 0
00877
00878
00879
00880
00881 char **xextensionlist;
00882 int nextensions, xtn;
00883 int warncompositeext=0;
00884 xextensionlist = XListExtensions(glxsrv.dpy, &nextensions);
00885 for (xtn=0; xtn<nextensions; xtn++) {
00886
00887 if (xextensionlist[xtn] && !strcmp(xextensionlist[xtn], "Composite")) {
00888 warncompositeext=1;
00889 }
00890 }
00891 if (warncompositeext) {
00892 msgWarn << "Detected X11 'Composite' extension: if incorrect display occurs" << sendmsg;
00893 msgWarn << "try disabling this X server option. Most OpenGL drivers" << sendmsg;
00894 msgWarn << "disable stereoscopic display when 'Composite' is enabled." << sendmsg;
00895 }
00896 XFreeExtensionList(xextensionlist);
00897 #endif
00898
00899
00900
00901
00902
00903 glxsrv.dpyScreen = DefaultScreen(glxsrv.dpy);
00904 glxsrv.rootWindowID = RootWindow(glxsrv.dpy, glxsrv.dpyScreen);
00905 screenX = DisplayWidth(glxsrv.dpy, glxsrv.dpyScreen);
00906 screenY = DisplayHeight(glxsrv.dpy, glxsrv.dpyScreen);
00907 W = size[0];
00908 H = size[1];
00909 if (loc) {
00910 SX = loc[0];
00911
00912
00913 SY = (screenY - loc[1]) - H;
00914 }
00915
00916
00917 if (!glXQueryExtension(glxsrv.dpy, NULL, NULL)) {
00918 msgErr << "The X server does not support the OpenGL GLX extension."
00919 << " Exiting ..." << sendmsg;
00920 XCloseDisplay(glxsrv.dpy);
00921 return (Window)0;
00922 }
00923
00924 ext->hasstereo = TRUE;
00925 ext->stereodrawforced = FALSE;
00926 ext->hasmultisample = TRUE;
00927
00928
00929 XVisualInfo *vi;
00930 vi = vmd_get_visual(&glxsrv, &ext->hasstereo, &ext->hasmultisample, &ext->nummultisamples);
00931
00932
00933 if (!vi) {
00934 msgErr << "A TrueColor visual is required, but not available." << sendmsg;
00935 msgErr << "The X server is not capable of displaying double-buffered," << sendmsg;
00936 msgErr << "RGB images with a Z buffer. Exiting ..." << sendmsg;
00937 XCloseDisplay(glxsrv.dpy);
00938 return (Window)0;
00939 }
00940
00941
00942 if(!(glxsrv.cx = glXCreateContext(glxsrv.dpy, vi, None, GL_TRUE))) {
00943 msgErr << "Could not create OpenGL rendering context-> Exiting..."
00944 << sendmsg;
00945 return (Window)0;
00946 }
00947
00948
00949 glxsrv.cursor[0] = XCreateFontCursor(glxsrv.dpy, XC_left_ptr);
00950 glxsrv.cursor[1] = XCreateFontCursor(glxsrv.dpy, XC_fleur);
00951 glxsrv.cursor[2] = XCreateFontCursor(glxsrv.dpy, XC_sb_h_double_arrow);
00952 glxsrv.cursor[3] = XCreateFontCursor(glxsrv.dpy, XC_crosshair);
00953 glxsrv.cursor[4] = XCreateFontCursor(glxsrv.dpy, XC_watch);
00954 for(i=0; i < 5; i++)
00955 XRecolorCursor(glxsrv.dpy, glxsrv.cursor[i], &cursorFG, &cursorBG);
00956
00957
00958
00959
00960
00961 XSetWindowAttributes swa;
00962
00963
00964
00965 swa.colormap = XCreateColormap(glxsrv.dpy, glxsrv.rootWindowID,
00966 vi->visual, AllocNone);
00967
00968 swa.background_pixmap = None;
00969 swa.border_pixel=0;
00970 swa.event_mask = ExposureMask;
00971 swa.cursor = glxsrv.cursor[0];
00972
00973 win = XCreateWindow(glxsrv.dpy, glxsrv.rootWindowID, SX, SY, W, H, 0,
00974 vi->depth, InputOutput, vi->visual,
00975 CWBorderPixel | CWColormap | CWEventMask, &swa);
00976 XInstallColormap(glxsrv.dpy, swa.colormap);
00977
00978 XFree(vi);
00979
00980
00981
00982
00983 memset((void *) &(glxsrv.sizeHints), 0, sizeof(glxsrv.sizeHints));
00984 glxsrv.sizeHints.flags |= USSize;
00985 glxsrv.sizeHints.flags |= USPosition;
00986 glxsrv.sizeHints.width = W;
00987 glxsrv.sizeHints.height = H;
00988 glxsrv.sizeHints.x = SX;
00989 glxsrv.sizeHints.y = SY;
00990
00991 XSetStandardProperties(glxsrv.dpy, win, nm, "VMD", None, argv, argc, &glxsrv.sizeHints);
00992 XWMHints *wmHints = XAllocWMHints();
00993 wmHints->initial_state = NormalState;
00994 wmHints->flags = StateHint;
00995 XSetWMHints(glxsrv.dpy, win, wmHints);
00996 XFree(wmHints);
00997
00998
00999 #if !defined(VMD_NANOHUB)
01000 Atom wmDeleteWindow = XInternAtom(glxsrv.dpy, "WM_DELETE_WINDOW", False);
01001 #else
01002 Atom wmDeleteWindow = XInternAtom(glxsrv.dpy, "WM_DELETE_WINDOW", True);
01003 #endif
01004 XSetWMProtocols(glxsrv.dpy, win, &wmDeleteWindow, 1);
01005
01006
01007 glXMakeCurrent(glxsrv.dpy, win, glxsrv.cx);
01008
01009
01010
01011 XSelectInput(glxsrv.dpy, win,
01012 KeyPressMask | ButtonPressMask | ButtonReleaseMask |
01013 StructureNotifyMask | ExposureMask |
01014 EnterWindowMask | LeaveWindowMask | FocusChangeMask);
01015 XMapRaised(glxsrv.dpy, win);
01016
01017
01018
01019 if (ext->hasmultisample) {
01020 int msampeext = 0;
01021
01022
01023 if (ext->vmdQueryExtension("GL_ARB_multisample")) {
01024 msampeext = 1;
01025 }
01026
01027 if (!msampeext) {
01028 ext->hasmultisample = FALSE;
01029 ext->nummultisamples = 0;
01030 }
01031 }
01032
01033
01034 setup_initial_opengl_state();
01035
01036 #if defined(VMDXINPUT)
01037
01038 if (getenv("VMDDISABLEXINPUT") == NULL) {
01039 glxsrv.xinp = xinput_enable(glxsrv.dpy, win);
01040 }
01041 #endif
01042
01043
01044
01045 if (getenv("VMDDISABLESPACEBALLXDRV") == NULL) {
01046 if (getenv("VMDSPACEBALLXDRVGLOBALFOCUS") == NULL) {
01047
01048 glxsrv.sball = spaceball_enable(glxsrv.dpy, InputFocus);
01049 } else {
01050
01051 glxsrv.sball = spaceball_enable(glxsrv.dpy, win);
01052 }
01053 }
01054 if (glxsrv.sball != NULL) {
01055 msgInfo << "X-Windows ClientMessage-based Spaceball device available."
01056 << sendmsg;
01057 }
01058
01059
01060
01061 spaceball_init_event(&glxsrv.sballevent);
01062
01063
01064 have_window = TRUE;
01065
01066
01067 return win;
01068 }
01069
01070
01071 int OpenGLDisplayDevice::prepare3D(int do_clear) {
01072
01073
01074 glXMakeCurrent(glxsrv.dpy, glxsrv.windowID, glxsrv.cx);
01075
01076 return OpenGLRenderer::prepare3D(do_clear);
01077 }
01078
01079
01080 void OpenGLDisplayDevice::do_resize_window(int w, int h) {
01081 if (getenv("VMDFULLSCREEN")) {
01082 int xinescreen=0;
01083 if (getenv("VMDXINESCREEN")) {
01084 xinescreen = atoi(getenv("VMDXINESCREEN"));
01085 }
01086 setfullscreen(1, glxsrv.dpy, glxsrv.windowID, xinescreen);
01087 } else {
01088 setfullscreen(0, glxsrv.dpy, glxsrv.windowID, -1);
01089 XResizeWindow(glxsrv.dpy, glxsrv.windowID, w, h);
01090 }
01091
01092 #if defined(VMDOPTIXRTRT)
01093 if (ort != NULL) ort->framebuffer_resize(w, h);
01094 #endif
01095 }
01096
01097 void OpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
01098 XMoveWindow(glxsrv.dpy, glxsrv.windowID, xpos, ypos);
01099 }
01100
01102
01103
01104
01105
01106
01107
01108 int OpenGLDisplayDevice::x(void) {
01109 Window rw, cw;
01110 int rx, ry, wx, wy;
01111 unsigned int keymask;
01112
01113
01114 XQueryPointer(glxsrv.dpy, glxsrv.windowID, &rw, &cw, &rx, &ry, &wx, &wy, &keymask);
01115
01116
01117 return rx;
01118 }
01119
01120
01121
01122 int OpenGLDisplayDevice::y(void) {
01123 Window rw, cw;
01124 int rx, ry, wx, wy;
01125 unsigned int keymask;
01126
01127
01128 XQueryPointer(glxsrv.dpy, glxsrv.windowID, &rw, &cw, &rx, &ry, &wx, &wy, &keymask);
01129
01130
01131
01132
01133 return screenY - ry;
01134 }
01135
01136
01137 int OpenGLDisplayDevice::shift_state(void) {
01138 int retval = 0;
01139
01140
01141 Window rw, cw;
01142 int rx, ry, wx, wy;
01143 unsigned int keymask;
01144 XQueryPointer(glxsrv.dpy, glxsrv.windowID, &rw, &cw, &rx, &ry, &wx, &wy, &keymask);
01145
01146
01147 if ((keymask & ShiftMask) != 0)
01148 retval |= SHIFT;
01149
01150 if ((keymask & ControlMask) != 0)
01151 retval |= CONTROL;
01152
01153 if ((keymask & Mod1Mask) != 0)
01154 retval |= ALT;
01155
01156
01157 return retval;
01158 }
01159
01160
01161
01162 int OpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty,
01163 int *tz, int *buttons) {
01164
01165 if ((glxsrv.sball != NULL || glxsrv.xinp != NULL)
01166 && glxsrv.sballevent.event == 1) {
01167 *rx = glxsrv.sballevent.rx;
01168 *ry = glxsrv.sballevent.ry;
01169 *rz = glxsrv.sballevent.rz;
01170 *tx = glxsrv.sballevent.tx;
01171 *ty = glxsrv.sballevent.ty;
01172 *tz = glxsrv.sballevent.tz;
01173 *buttons = glxsrv.sballevent.buttons;
01174 return 1;
01175 }
01176
01177 return 0;
01178 }
01179
01180
01181
01182
01183 void OpenGLDisplayDevice::set_cursor(int n) {
01184 int cursorindex;
01185
01186 switch (n) {
01187 default:
01188 case DisplayDevice::NORMAL_CURSOR: cursorindex = 0; break;
01189 case DisplayDevice::TRANS_CURSOR: cursorindex = 1; break;
01190 case DisplayDevice::SCALE_CURSOR: cursorindex = 2; break;
01191 case DisplayDevice::PICK_CURSOR: cursorindex = 3; break;
01192 case DisplayDevice::WAIT_CURSOR: cursorindex = 4; break;
01193 }
01194
01195 XDefineCursor(glxsrv.dpy, glxsrv.windowID, glxsrv.cursor[cursorindex]);
01196 }
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206 void OpenGLDisplayDevice::queue_events(void) {
01207 XSelectInput(glxsrv.dpy, glxsrv.windowID,
01208 KeyPressMask | ButtonPressMask | ButtonReleaseMask |
01209 StructureNotifyMask | ExposureMask |
01210 EnterWindowMask | LeaveWindowMask | FocusChangeMask);
01211 }
01212
01213
01214
01215
01216
01217 int OpenGLDisplayDevice::read_event(long &retdev, long &retval) {
01218 XEvent xev;
01219 char keybuf[10];
01220 int keybuflen = 9;
01221 KeySym keysym;
01222 XComposeStatus comp;
01223
01224 memset(keybuf, 0, sizeof(keybuf));
01225
01226
01227
01228 spaceball_clear_event(&glxsrv.sballevent);
01229
01230 retdev = WIN_NOEVENT;
01231
01232
01233 int need_reshape = FALSE;
01234 while (XPending(glxsrv.dpy)) {
01235 XNextEvent(glxsrv.dpy, &xev);
01236
01237
01238 switch(xev.type) {
01239 case Expose:
01240 case ConfigureNotify:
01241 case ReparentNotify:
01242 case MapNotify:
01243 need_reshape = TRUE;
01244 _needRedraw = 1;
01245
01246 break;
01247 case KeyPress:
01248 {
01249 int k = XLookupString(&(xev.xkey), keybuf, keybuflen, &keysym, &comp);
01250
01251 if (k > 0 && *keybuf != '\0') {
01252 retdev = WIN_KBD;
01253 retval = *keybuf;
01254 } else {
01255 switch (keysym) {
01256 case XK_Escape: retdev = WIN_KBD_ESCAPE; break;
01257 case XK_Up: retdev = WIN_KBD_UP; break;
01258 case XK_Down: retdev = WIN_KBD_DOWN; break;
01259 case XK_Left: retdev = WIN_KBD_LEFT; break;
01260 case XK_Right: retdev = WIN_KBD_RIGHT; break;
01261 case XK_Page_Up: retdev = WIN_KBD_PAGE_UP; break;
01262 case XK_Page_Down: retdev = WIN_KBD_PAGE_UP; break;
01263 case XK_Home: retdev = WIN_KBD_HOME; break;
01264 case XK_End: retdev = WIN_KBD_END; break;
01265 case XK_Insert: retdev = WIN_KBD_INSERT; break;
01266 case XK_Delete: retdev = WIN_KBD_DELETE; break;
01267 case XK_F1: retdev = WIN_KBD_F1; break;
01268 case XK_F2: retdev = WIN_KBD_F2; break;
01269 case XK_F3: retdev = WIN_KBD_F3; break;
01270 case XK_F4: retdev = WIN_KBD_F4; break;
01271 case XK_F5: retdev = WIN_KBD_F5; break;
01272 case XK_F6: retdev = WIN_KBD_F6; break;
01273 case XK_F7: retdev = WIN_KBD_F7; break;
01274 case XK_F8: retdev = WIN_KBD_F8; break;
01275 case XK_F9: retdev = WIN_KBD_F9; break;
01276 case XK_F10: retdev = WIN_KBD_F10; break;
01277 case XK_F11: retdev = WIN_KBD_F11; break;
01278 case XK_F12: retdev = WIN_KBD_F12; break;
01279 }
01280 }
01281 break;
01282 }
01283 case ButtonPress:
01284 case ButtonRelease:
01285 {
01286 unsigned int button = xev.xbutton.button;
01287 retval = (xev.type == ButtonPress);
01288 switch (button) {
01289 case Button1:
01290 retdev = WIN_LEFT;
01291 break;
01292 case Button2:
01293 retdev = WIN_MIDDLE;
01294 break;
01295 case Button3:
01296 retdev = WIN_RIGHT;
01297 break;
01298 case Button4:
01299 retdev = WIN_WHEELUP;
01300 break;
01301 case Button5:
01302 retdev = WIN_WHEELDOWN;
01303 break;
01304 }
01305 break;
01306 }
01307 break;
01308
01309 case FocusIn:
01310 case EnterNotify:
01311 glxsrv.havefocus=1;
01312 break;
01313
01314 case FocusOut:
01315 case LeaveNotify:
01316 glxsrv.havefocus=0;
01317 break;
01318
01319 case ClientMessage:
01320 #if 1
01321
01322
01323 spaceball_decode_event(glxsrv.sball, &xev, &glxsrv.sballevent);
01324 #else
01325
01326
01327 if (glxsrv.havefocus) {
01328 spaceball_decode_event(glxsrv.sball, &xev, &glxsrv.sballevent);
01329 }
01330 #endif
01331 break;
01332
01333 default:
01334 #if defined(VMDXINPUT)
01335 if (glxsrv.xinp != NULL) {
01336 if (xinput_decode_event((xinputhandle *) glxsrv.xinp, &xev,
01337 &glxsrv.sballevent)) {
01338 break;
01339 }
01340 }
01341 #endif
01342
01343 #if 0
01344 msgWarn << "Unrecognized X11 event" << xev.type << sendmsg;
01345 #endif
01346 break;
01347
01348 }
01349 }
01350
01351 if (need_reshape)
01352 reshape();
01353
01354 return (retdev != WIN_NOEVENT);
01355 }
01356
01357
01358
01359
01360
01361
01362 void OpenGLDisplayDevice::reshape(void) {
01363
01364
01365 XWindowAttributes xwa;
01366 Window childwin;
01367 int rx, ry;
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382 XGetWindowAttributes(glxsrv.dpy, glxsrv.windowID, &xwa);
01383 XTranslateCoordinates(glxsrv.dpy, glxsrv.windowID, glxsrv.rootWindowID, -xwa.border_width,
01384 -xwa.border_width, &rx, &ry, &childwin);
01385
01386 xSize = xwa.width;
01387 ySize = xwa.height;
01388 xOrig = rx;
01389 yOrig = screenY - ry - ySize;
01390
01391 switch (inStereo) {
01392 case OPENGL_STEREO_SIDE:
01393 set_screen_pos(0.5f * (float)xSize / (float)ySize);
01394 break;
01395
01396 case OPENGL_STEREO_ABOVEBELOW:
01397 set_screen_pos(2.0f * (float)xSize / (float)ySize);
01398 break;
01399
01400 case OPENGL_STEREO_STENCIL_CHECKERBOARD:
01401 case OPENGL_STEREO_STENCIL_COLUMNS:
01402 case OPENGL_STEREO_STENCIL_ROWS:
01403 enable_stencil_stereo(inStereo);
01404 set_screen_pos((float)xSize / (float)ySize);
01405 break;
01406
01407 default:
01408 set_screen_pos((float)xSize / (float)ySize);
01409 break;
01410 }
01411 #if defined(VMD_NANOHUB)
01412 init_offscreen_framebuffer(xSize, ySize);
01413 #endif
01414 }
01415
01416
01417 unsigned char * OpenGLDisplayDevice::readpixels_rgb3u(int &xs, int &ys) {
01418 unsigned char * img = NULL;
01419 xs = xSize;
01420 ys = ySize;
01421
01422
01423 if ((img = (unsigned char *) malloc(xs * ys * 3)) != NULL) {
01424 glPixelStorei(GL_PACK_ALIGNMENT, 1);
01425 glReadPixels(0, 0, xs, ys, GL_RGB, GL_UNSIGNED_BYTE, img);
01426 return img;
01427 }
01428
01429
01430 xs = 0;
01431 ys = 0;
01432 return NULL;
01433 }
01434
01435 unsigned char * OpenGLDisplayDevice::readpixels_rgba4u(int &xs, int &ys) {
01436 unsigned char * img = NULL;
01437 xs = xSize;
01438 ys = ySize;
01439
01440
01441 if ((img = (unsigned char *) malloc(xs * ys * 4)) != NULL) {
01442 glPixelStorei(GL_PACK_ALIGNMENT, 1);
01443 glReadPixels(0, 0, xs, ys, GL_RGBA, GL_UNSIGNED_BYTE, img);
01444 return img;
01445 }
01446
01447
01448 xs = 0;
01449 ys = 0;
01450 return NULL;
01451 }
01452
01453
01454 int OpenGLDisplayDevice::drawpixels_rgba4u(unsigned char *rgba, int &xs, int &ys) {
01455
01456 #if 0
01457
01458
01459
01460
01461
01462 glPushMatrix();
01463 glDisable(GL_DEPTH_TEST);
01464
01465 glViewport(0, 0, xs, ys);
01466
01467 glShadeModel(GL_FLAT);
01468 glMatrixMode(GL_PROJECTION);
01469 glLoadIdentity();
01470 glOrtho(0.0, xs, 0.0, ys, -1.0, 1.0);
01471 glMatrixMode(GL_MODELVIEW);
01472 glLoadIdentity();
01473 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01474 glPixelZoom(1.0, 1.0);
01475
01476 glRasterPos2i(0, 0);
01477 glDrawPixels(xs, ys, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
01478
01479 glEnable(GL_DEPTH_TEST);
01480 glPopMatrix();
01481 #elif 1
01482
01483
01484
01485
01486
01487 glPushMatrix();
01488 glDisable(GL_DEPTH_TEST);
01489
01490 glViewport(0, 0, xs, ys);
01491
01492 glShadeModel(GL_FLAT);
01493 glMatrixMode(GL_PROJECTION);
01494 glLoadIdentity();
01495 glOrtho(0.0, xs, 0.0, ys, -1.0, 1.0);
01496 glMatrixMode(GL_MODELVIEW);
01497
01498 GLuint texName = 0;
01499 GLfloat texborder[4] = {0.0, 0.0, 0.0, 1.0};
01500 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01501 glBindTexture(GL_TEXTURE_2D, texName);
01502
01503
01504 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, texborder);
01505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
01506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
01507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01509 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01510
01511 glLoadIdentity();
01512 glColor3f(1.0, 1.0, 1.0);
01513
01514 #if 1
01515 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0,
01516 GL_RGBA, GL_UNSIGNED_BYTE, rgba);
01517 glEnable(GL_TEXTURE_2D);
01518 #endif
01519
01520 glBegin(GL_QUADS);
01521 glTexCoord2f(0.0f, 0.0f);
01522 glVertex2f(0, 0);
01523 glTexCoord2f(0.0f, 1.0f);
01524 glVertex2f(0, GLfloat(ys));
01525 glTexCoord2f(1.0f, 1.0f);
01526 glVertex2f(GLfloat(xs), GLfloat(ys));
01527 glTexCoord2f(1.0f, 0.0f);
01528 glVertex2f(GLfloat(xs), 0.0f);
01529 glEnd();
01530
01531 #if 1
01532 glDisable(GL_TEXTURE_2D);
01533 #endif
01534
01535 glEnable(GL_DEPTH_TEST);
01536 glPopMatrix();
01537 #endif
01538
01539 update();
01540
01541 return 0;
01542 }
01543
01544
01545
01546 void OpenGLDisplayDevice::update(int do_update) {
01547 if (wiregl) {
01548 glFinish();
01549
01550
01551 }
01552
01553 #if 1
01554
01555
01556 if (vmdapp->uivs && vmdapp->uivs->srv_connected()) {
01557
01558 int xs, ys;
01559 unsigned char *img = NULL;
01560 img = readpixels_rgba4u(xs, ys);
01561 if (img != NULL) {
01562
01563 vmdapp->uivs->video_frame_pending(img, xs, ys);
01564 vmdapp->uivs->check_event();
01565 free(img);
01566 }
01567 }
01568 #endif
01569
01570 #if !defined(VMD_NANOHUB)
01571
01572 if (do_update)
01573 glXSwapBuffers(glxsrv.dpy, glxsrv.windowID);
01574 #endif
01575
01576 glDrawBuffer(GL_BACK);
01577 }
01578
01579
01580 void OpenGLDisplayDevice::set_window_title(char *newtitlestr) {
01581 #if !defined(VMDSDL) && !defined(_MSC_VER)
01582 XStoreName(glxsrv.dpy, glxsrv.windowID, newtitlestr);
01583 #endif
01584 }
01585
01586
01587
01588