00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include "FltkOpenGLDisplayDevice.h"
00028 #include "Inform.h"
00029 #include "utilities.h"
00030 #include "config.h"
00031 #include "VMDApp.h"
00032 #include "FL/Fl.H"
00033 #include "FL/Fl_Gl_Window.H"
00034 #include "FL/forms.H"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #if defined(__APPLE__)
00063 #if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 3) && (FL_PATCH_VERSION >= 5)) || (FL_MINOR_VERSION >= 4))
00064 #define VMDFLTKUSEHIGHDPIRETINA 1
00065 #endif
00066 #endif
00067
00070 class myglwindow : public Fl_Gl_Window {
00071 FltkOpenGLDisplayDevice *dispdev;
00072 VMDApp *app;
00073 int dragpending;
00074
00075 public:
00076 myglwindow(int wx, int wy, int width, int height, const char *nm,
00077 FltkOpenGLDisplayDevice *d, VMDApp *vmdapp)
00078 : Fl_Gl_Window(wx, wy, width, height, nm), dispdev(d), app(vmdapp), dragpending(0) {
00079
00080 size_range(1,1,0,0);
00081 }
00082
00083
00084 int handle(int event) {
00085
00086 if (event == FL_PASTE) {
00087
00088
00089 if (dragpending) {
00090 int len = Fl::event_length();
00091
00092
00093 if (len > 0) {
00094 int numfiles, i;
00095 const char *lastc;
00096 int lasti;
00097 FileSpec spec;
00098 const char *ctext = Fl::event_text();
00099 char *filename = (char *) malloc((1 + len) * sizeof(char));
00100
00101 for (lasti=0,lastc=ctext,numfiles=0,i=0; i<len; i++) {
00102
00103 if (ctext[i] == '\n') {
00104 memcpy(filename, lastc, (i-lasti)*sizeof(char));
00105 filename[i-lasti] = '\0';
00106
00107
00108 app->molecule_load(-1, filename, NULL, &spec);
00109
00110 lasti=i+1;
00111 lastc=&ctext[lasti];
00112 numfiles++;
00113 }
00114
00115
00116 if (i == (len-1)) {
00117 memcpy(filename, lastc, (1+i-lasti)*sizeof(char));
00118 filename[1+i-lasti] = '\0';
00119
00120
00121 app->molecule_load(-1, filename, NULL, &spec);
00122 numfiles++;
00123 }
00124 }
00125
00126 free(filename);
00127 }
00128
00129 dragpending = 0;
00130 }
00131
00132 return 1;
00133 }
00134
00135
00136 if (event == FL_DND_ENTER || event == FL_DND_DRAG) {
00137 return 1;
00138 }
00139 if (event == FL_DND_RELEASE) {
00140 Fl::paste(*this);
00141 dragpending = 1;
00142 return 1;
00143 }
00144
00145
00146 switch (event) {
00147 case FL_MOUSEWHEEL:
00148 dispdev->lastevent = event;
00149 dispdev->lastzdelta = Fl::event_dy();
00150 break;
00151 case FL_PUSH:
00152 dispdev->lastevent = event;
00153 dispdev->lastbtn = Fl::event_button();
00154 if (dispdev->lastbtn == FL_LEFT_MOUSE && Fl::event_state(FL_META)) {
00155 dispdev->lastbtn = FL_MIDDLE_MOUSE;
00156 }
00157 break;
00158 case FL_DRAG:
00159 dispdev->lastevent = event;
00160 break;
00161 case FL_RELEASE:
00162 dispdev->lastevent = event;
00163 break;
00164 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00165 case FL_KEYDOWN:
00166 #else
00167
00168 case FL_KEYBOARD:
00169 #endif
00170 dispdev->lastevent = event;
00171 dispdev->lastkeycode = Fl::event_key();
00172 dispdev->lastbtn = *Fl::event_text();
00173 break;
00174 default:
00175 return Fl_Gl_Window::handle(event);
00176 }
00177 return 1;
00178 }
00179 void draw() {
00180 dispdev->reshape();
00181 dispdev->_needRedraw = 1;
00182 app->VMDupdate(VMD_IGNORE_EVENTS);
00183 }
00184
00185 void hide() {
00186 if (fl_show_question("Really Quit?", 0))
00187 app->VMDexit("",0,0);
00188 }
00189 };
00190
00191
00192
00193 static const char *glStereoNameStr[OPENGL_STEREO_MODES] =
00194 { "Off",
00195 "QuadBuffered",
00196 "HDTV SideBySide",
00197 "Checkerboard",
00198 "ColumnInterleaved",
00199 "RowInterleaved",
00200 "Anaglyph",
00201 "SideBySide",
00202 "AboveBelow",
00203 "Left",
00204 "Right" };
00205
00206 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00207 { "Normal",
00208 "GLSL",
00209 "Acrobat3D" };
00210
00211 static const char *glCacheNameStr[OPENGL_CACHE_MODES] =
00212 { "Off",
00213 "On" };
00214
00216
00217
00218 FltkOpenGLDisplayDevice::FltkOpenGLDisplayDevice(int argc, char **argv,
00219 VMDApp *vmdapp_p, int *size, int *loc)
00220 : OpenGLRenderer((char *) "VMD " VMDVERSION " OpenGL Display") {
00221
00222 vmdapp = vmdapp_p;
00223
00224
00225
00226 stereoNames = glStereoNameStr;
00227 stereoModes = OPENGL_STEREO_MODES;
00228
00229
00230 renderNames = glRenderNameStr;
00231 renderModes = OPENGL_RENDER_MODES;
00232
00233 cacheNames = glCacheNameStr;
00234 cacheModes = OPENGL_CACHE_MODES;
00235
00236 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00237 if (getenv("VMDNOHIGHDPI") != NULL) {
00238 msgWarn << "User override: High-DPI OpenGL display support disabled." << sendmsg;
00239 } else {
00240
00241
00242
00243
00244
00245
00246 Fl::use_high_res_GL(1);
00247 msgInfo << "High-DPI OpenGL display support enabled." << sendmsg;
00248 }
00249 #endif
00250
00251
00252 int SX = 100, SY = 100, W, H;
00253
00254 W = size[0];
00255 H = size[1];
00256 if (loc) {
00257 SX = loc[0];
00258 SY = loc[1];
00259 }
00260 window = new myglwindow(SX, SY, W, H, name, this, vmdapp_p);
00261
00262 ext->hasstereo = FALSE;
00263 ext->stereodrawforced = FALSE;
00264 ext->hasmultisample = FALSE;
00265
00266 int rc=0;
00267
00268 #if (FL_MAJOR_VERSION >= 1) && (((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)) || ((FL_MINOR_VERSION >= 1) && (FL_PATCH_VERSION >= 7)))
00269
00270 if (getenv("VMDPREFERSTEREO") != NULL) {
00271
00272 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_STEREO);
00273 ext->hasstereo = TRUE;
00274 #if defined(__APPLE__)
00275 ext->stereodrawforced = TRUE;
00276 #endif
00277
00278
00279 #if !defined(__APPLE__)
00280
00281 } else if (rc != 0) {
00282 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL | FL_MULTISAMPLE);
00283 ext->hasmultisample = TRUE;
00284 #endif
00285 } else {
00286 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00287 }
00288 #else
00289
00290 rc = window->mode(FL_RGB8 | FL_DOUBLE | FL_STENCIL);
00291 #endif
00292
00293 window->show();
00294
00295 window->make_current();
00296
00297
00298 screenX = Fl::w();
00299 screenY = Fl::h();
00300
00301
00302 setup_initial_opengl_state();
00303
00304
00305
00306 if (ext->hasmultisample)
00307 aaAvailable = TRUE;
00308 else
00309 aaAvailable = FALSE;
00310
00311
00312 if (ext->hasmultisample) {
00313 aa_on();
00314
00315
00316 }
00317
00318 cueingAvailable = TRUE;
00319 cueing_on();
00320
00321 cullingAvailable = TRUE;
00322 culling_off();
00323
00324 set_sphere_mode(sphereMode);
00325 set_sphere_res(sphereRes);
00326 set_line_width(lineWidth);
00327 set_line_style(lineStyle);
00328
00329
00330 reshape();
00331 normal();
00332 clear();
00333 update();
00334 }
00335
00336
00337 FltkOpenGLDisplayDevice::~FltkOpenGLDisplayDevice(void) {
00338 free_opengl_ctx();
00339 delete window;
00340 }
00341
00343
00344
00345
00346
00347
00348
00349 int FltkOpenGLDisplayDevice::x(void) {
00350
00351 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00352
00353
00354
00355
00356
00357
00358
00359
00360 return Fl::event_x_root() * window->pixels_per_unit();
00361 #elif 1
00362 return Fl::event_x_root();
00363 #else
00364 int x, y;
00365 Fl::get_mouse(x, y);
00366 return x;
00367 #endif
00368 }
00369
00370
00371
00372 int FltkOpenGLDisplayDevice::y(void) {
00373
00374 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00375
00376
00377
00378
00379
00380
00381
00382
00383 return screenY - (Fl::event_y_root() * window->pixels_per_unit());
00384 #elif 1
00385 return screenY - Fl::event_y_root();
00386 #else
00387 int x, y;
00388 Fl::get_mouse(x, y);
00389 return screenY - y;
00390 #endif
00391 }
00392
00393
00394 int FltkOpenGLDisplayDevice::shift_state(void) {
00395 Fl::check();
00396
00397 int retval = 0;
00398 int keymask = (int) Fl::event_state();
00399 if (keymask & FL_SHIFT)
00400 retval |= SHIFT;
00401 if (keymask & FL_CTRL)
00402 retval |= CONTROL;
00403 if (keymask & FL_ALT)
00404 retval |= ALT;
00405 return retval;
00406 }
00407
00408
00409 int FltkOpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty,
00410 int *tz, int *buttons) {
00411
00412 return 0;
00413 }
00414
00415
00416
00417
00418 void FltkOpenGLDisplayDevice::set_cursor(int n) {
00419 switch (n) {
00420 default:
00421 case DisplayDevice::NORMAL_CURSOR: window->cursor(FL_CURSOR_ARROW); break;
00422 case DisplayDevice::TRANS_CURSOR: window->cursor(FL_CURSOR_MOVE); break;
00423 case DisplayDevice::SCALE_CURSOR: window->cursor(FL_CURSOR_WE); break;
00424 case DisplayDevice::PICK_CURSOR: window->cursor(FL_CURSOR_CROSS); break;
00425 case DisplayDevice::WAIT_CURSOR: window->cursor(FL_CURSOR_WAIT); break;
00426 }
00427 }
00428
00429
00430
00431
00432
00433
00434
00435
00436 int FltkOpenGLDisplayDevice::read_event(long &retdev, long &retval) {
00437 #if !defined(__APPLE__)
00438
00439
00440
00441
00442 Fl::check();
00443 #endif
00444
00445 switch (lastevent) {
00446 case FL_MOUSEWHEEL:
00447
00448
00449 if (lastzdelta < 0) {
00450 retdev = WIN_WHEELUP;
00451 } else {
00452 retdev = WIN_WHEELDOWN;
00453 }
00454 break;
00455 case FL_PUSH:
00456 case FL_DRAG:
00457 case FL_RELEASE:
00458 if (lastbtn == FL_LEFT_MOUSE) retdev = WIN_LEFT;
00459 else if (lastbtn == FL_MIDDLE_MOUSE) retdev = WIN_MIDDLE;
00460 else if (lastbtn == FL_RIGHT_MOUSE) retdev = WIN_RIGHT;
00461 else {
00462
00463 }
00464 retval = (lastevent == FL_PUSH || lastevent == FL_DRAG);
00465 break;
00466
00467 #if (FL_MAJOR_VERSION >= 1) && (FL_MINOR_VERSION >= 1)
00468 case FL_KEYDOWN:
00469 #else
00470
00471 case FL_KEYBOARD:
00472 #endif
00473
00474 if (lastkeycode >= FL_F && lastkeycode <= FL_F_Last) {
00475 retdev = (lastkeycode - FL_F) + ((int) WIN_KBD_F1);
00476 } else {
00477 switch(lastkeycode) {
00478 case FL_Escape: retdev = WIN_KBD_ESCAPE; break;
00479 case FL_Up: retdev = WIN_KBD_UP; break;
00480 case FL_Down: retdev = WIN_KBD_DOWN; break;
00481 case FL_Left: retdev = WIN_KBD_LEFT; break;
00482 case FL_Right: retdev = WIN_KBD_RIGHT; break;
00483 case FL_Page_Up: retdev = WIN_KBD_PAGE_UP; break;
00484 case FL_Page_Down: retdev = WIN_KBD_PAGE_UP; break;
00485 case FL_Home: retdev = WIN_KBD_HOME; break;
00486 case FL_End: retdev = WIN_KBD_END; break;
00487 case FL_Insert: retdev = WIN_KBD_INSERT; break;
00488 case FL_Delete: retdev = WIN_KBD_DELETE; break;
00489
00490 default:
00491 retdev = WIN_KBD;
00492 break;
00493 }
00494 }
00495 retval = lastbtn;
00496 break;
00497
00498 default:
00499 return 0;
00500 }
00501 lastevent = 0;
00502 return 1;
00503 }
00504
00505
00506
00507
00508
00509
00510 void FltkOpenGLDisplayDevice::reshape(void) {
00511
00512 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00513
00514
00515 xSize = window->w() * window->pixels_per_unit();
00516 ySize = window->h() * window->pixels_per_unit();
00517 xOrig = window->x() * window->pixels_per_unit();
00518 yOrig = screenY - (window->y() * window->pixels_per_unit()) - ySize;
00519 #else
00520 xSize = window->w();
00521 ySize = window->h();
00522 xOrig = window->x();
00523 yOrig = screenY - window->y() - ySize;
00524 #endif
00525
00526 switch (inStereo) {
00527 case OPENGL_STEREO_SIDE:
00528 set_screen_pos(0.5f * (float)xSize / (float)ySize);
00529 break;
00530
00531 case OPENGL_STEREO_ABOVEBELOW:
00532 set_screen_pos(2.0f * (float)xSize / (float)ySize);
00533 break;
00534
00535 case OPENGL_STEREO_STENCIL_CHECKERBOARD:
00536 case OPENGL_STEREO_STENCIL_COLUMNS:
00537 case OPENGL_STEREO_STENCIL_ROWS:
00538 enable_stencil_stereo(inStereo);
00539 set_screen_pos((float)xSize / (float)ySize);
00540 break;
00541
00542 default:
00543 set_screen_pos((float)xSize / (float)ySize);
00544 break;
00545 }
00546 }
00547
00548 unsigned char * FltkOpenGLDisplayDevice::readpixels_rgb3u(int &x, int &y) {
00549 unsigned char * img;
00550
00551 x = xSize;
00552 y = ySize;
00553
00554 if ((img = (unsigned char *) malloc(x * y * 3)) != NULL) {
00555 #if !defined(WIREGL)
00556 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00557 glReadPixels(0, 0, x, y, GL_RGB, GL_UNSIGNED_BYTE, img);
00558 #endif
00559 } else {
00560 x = 0;
00561 y = 0;
00562 }
00563
00564 return img;
00565 }
00566
00567 unsigned char * FltkOpenGLDisplayDevice::readpixels_rgba4u(int &x, int &y) {
00568 unsigned char * img;
00569
00570 x = xSize;
00571 y = ySize;
00572
00573 if ((img = (unsigned char *) malloc(x * y * 4)) != NULL) {
00574 #if !defined(WIREGL)
00575 glPixelStorei(GL_PACK_ALIGNMENT, 1);
00576 glReadPixels(0, 0, x, y, GL_RGBA, GL_UNSIGNED_BYTE, img);
00577 #endif
00578 } else {
00579 x = 0;
00580 y = 0;
00581 }
00582
00583 return img;
00584 }
00585
00586
00587
00588 void FltkOpenGLDisplayDevice::update(int do_update) {
00589 if(do_update)
00590 window->swap_buffers();
00591
00592 glDrawBuffer(GL_BACK);
00593 }
00594
00595 void FltkOpenGLDisplayDevice::do_resize_window(int w, int h) {
00596 #if defined(VMDFLTKUSEHIGHDPIRETINA)
00597
00598
00599
00600 window->size(w / window->pixels_per_unit(), h / window->pixels_per_unit());
00601 #else
00602 window->size(w, h);
00603 #endif
00604
00605
00606 window->size_range(1,1,0,0);
00607 }
00608
00609 void FltkOpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
00610 window->position(xpos, ypos);
00611
00612 window->size_range(1,1,0,0);
00613 }
00614
00615