Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

Win32OpenGLDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr 
00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 
00004 *cr University of Illinois 
00005 *cr All Rights Reserved 
00006 *cr 
00007 ***************************************************************************/
00008 /***************************************************************************
00009 * RCS INFORMATION:
00010 *
00011 * $RCSfile: Win32OpenGLDisplayDevice.C,v $
00012 * $Author: johns $ $Locker: $ $State: Exp $
00013 * $Revision: 1.131 $ $Date: 2021年12月21日 23:20:58 $
00014 *
00015 ***************************************************************************/
00024 #ifndef _WIN32_WINNT
00025 #define _WIN32_WINNT 0x0400 // hack to allow access to mouse wheel events
00026 #endif
00027 #include <windows.h> // Mouse wheel events and related macros
00028 #include <winuser.h> // Mouse wheel events and related macros
00029 
00030 #include "VMDApp.h"
00031 #include "OpenGLDisplayDevice.h"
00032 #include "Inform.h"
00033 #include "utilities.h"
00034 #include "config.h" // VMD version strings etc
00035 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <math.h>
00039 #include <GL/gl.h>
00040 
00041 #include "../msvc/winvmd/res/resource.h" // VMD icon resource
00042 
00043 #if 1
00044 // 
00045 // Compile-time constant to provide hybrid graphics drivers with a hint to 
00046 // favor the use of the high performance GPU when one exists.
00047 // 
00048 extern "C" {
00049 // trigger AMD PowerXpress drivers to use the high performance GPU
00050 __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 1;
00051 
00052 // trigger NVIDIA Optimus drivers to use the high performance GPU
00053 __declspec(dllexport) DWORD NvOptimusEnablement = 1;
00054 }
00055 #endif
00056 
00057 
00058 // NOTE: you may have to get copies of the latest OpenGL extension headers
00059 // from the OpenGL web site if your Linux or Win32 machine lacks them:
00060 // http://oss.sgi.com/projects/ogl-sample/registry/
00061 #include <GL/glext.h> // include OpenGL extension headers
00062 #include <GL/wglext.h> // include OpenGL extension headers
00063 
00064 // static data for this object
00065 static const char *glStereoNameStr[OPENGL_STEREO_MODES] = 
00066 { "Off", 
00067 "QuadBuffered", 
00068 "HDTV SideBySide",
00069 "Checkerboard",
00070 "ColumnInterleaved",
00071 "RowInterleaved",
00072 "Anaglyph",
00073 "SideBySide", 
00074 "AboveBelow",
00075 "Left", 
00076 "Right" };
00077 
00078 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00079 { "Normal",
00080 "GLSL",
00081 "Acrobat3D" };
00082 
00083 static const char *glCacheNameStr[OPENGL_CACHE_MODES] = 
00084 { "Off",
00085 "On" };
00086 
00087 static char szAppName[] = "VMD";
00088 static char szAppTitle[]="VMD " VMDVERSION " OpenGL Display";
00089 
00090 LRESULT WINAPI vmdWindowProc( HWND, UINT, WPARAM, LPARAM );
00091 
00092 static int OpenWin32Connection(wgldata * glwsrv) {
00093 WNDCLASS wc;
00094 HINSTANCE hInstance = GetModuleHandle(NULL);
00095 
00096 /* Clear (important!) and then fill in the window class structure. */
00097 memset(&wc, 0, sizeof(WNDCLASS));
00098 wc.style = CS_OWNDC;
00099 wc.lpfnWndProc = (WNDPROC) vmdWindowProc;
00100 wc.hInstance = hInstance;
00101 #if 1
00102 // use our VMD icon
00103 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
00104 #else
00105 wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
00106 #endif
00107 wc.hCursor = LoadCursor(hInstance, IDC_ARROW);
00108 wc.hbrBackground = NULL; /* Default color */
00109 wc.lpszMenuName = NULL;
00110 wc.lpszClassName = szAppName;
00111 
00112 if(!RegisterClass(&wc)) {
00113 printf("Cannot register window class.\n");
00114 return -1;
00115 }
00116 
00117 // get screen size 
00118 // XXX There's no Win32 API to get the full multi-monitor desktop,
00119 // so this code doesn't correctly handle multi-monitor systems yet.
00120 // To correctly handle multiple monitors, we'd have to 
00121 // walk the device tree, take into account monitor layout/positioning, 
00122 // and compute the desktop dimensions from that. Since these values
00123 // are currently only used by do_reposition_window() method, we can
00124 // live with primary-monitor values for the time being.
00125 glwsrv->scrwidth = GetSystemMetrics(SM_CXSCREEN);
00126 glwsrv->scrheight = GetSystemMetrics(SM_CYSCREEN);
00127 
00128 return 0;
00129 }
00130 
00131 static int PFDHasStereo(int ID, HDC hDC) {
00132 PIXELFORMATDESCRIPTOR pfd;
00133 DescribePixelFormat(hDC, ID, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00134 
00135 #if 0
00136 // print a message if we find out we've got an accelerated mode
00137 if ((pfd.dwFlags & PFD_GENERIC_ACCELERATED) ||
00138 !(pfd.dwFlags & PFD_GENERIC_FORMAT)) 
00139 msgInfo << "Hardware 3D Acceleration enabled." << sendmsg;
00140 else
00141 msgInfo << "No hardware 3D Acceleration found." << sendmsg;
00142 #endif
00143 
00144 if (pfd.dwFlags & PFD_STEREO) 
00145 return 1;
00146 
00147 return 0;
00148 } 
00149 
00150 #if 0
00151 static void PrintPFD(int ID, HDC hDC) {
00152 PIXELFORMATDESCRIPTOR pfd;
00153 FILE * ofp;
00154 
00155 if (ID == 0) {
00156 int i, num;
00157 num = DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00158 for (i=1; i<num; i++) 
00159 PrintPFD(i, hDC);
00160 
00161 return;
00162 }
00163 
00164 DescribePixelFormat(hDC, ID, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00165 
00166 ofp=fopen("c:/video.txt", "a+");
00167 if (ofp == NULL) 
00168 ofp=stdout;
00169 
00170 if (pfd.cColorBits < 15) {
00171 fprintf(ofp, "Windows Pixel Format ID: %d -- not enough color bits\n", ID);
00172 }
00173 else {
00174 fprintf(ofp, "\nWindows Pixel Format ID: %d\n", ID);
00175 fprintf(ofp, " Color Buffer Depth: %d bits\n", pfd.cColorBits);
00176 fprintf(ofp, " Z Buffer Depth: %d bits\n", pfd.cDepthBits);
00177 if (pfd.dwFlags & PFD_DOUBLEBUFFER)
00178 fprintf(ofp, " PFD_DOUBLEBUFFER\n"); 
00179 if (pfd.dwFlags & PFD_STEREO)
00180 fprintf(ofp, " PFD_STEREO\n"); 
00181 if (pfd.dwFlags & PFD_DRAW_TO_WINDOW)
00182 fprintf(ofp, " PFD_DRAW_TO_WINDOW\n"); 
00183 if (pfd.dwFlags & PFD_SUPPORT_GDI)
00184 fprintf(ofp, " PFD_SUPPORT_GDI\n"); 
00185 if (pfd.dwFlags & PFD_SUPPORT_OPENGL)
00186 fprintf(ofp, " PFD_SUPPORT_OPENGL\n"); 
00187 if (pfd.dwFlags & PFD_SWAP_EXCHANGE) 
00188 fprintf(ofp, " PFD_SWAP_EXCHANGE\n"); 
00189 if (pfd.dwFlags & PFD_SWAP_COPY) 
00190 fprintf(ofp, " PFD_SWAP_COPY\n"); 
00191 if (pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS) 
00192 fprintf(ofp, " PFD_SWAP_LAYER_BUFFERS\n"); 
00193 if (pfd.dwFlags & PFD_GENERIC_ACCELERATED)
00194 fprintf(ofp, " PFD_GENERIC_ACCELERATED\n"); 
00195 if (pfd.dwFlags & PFD_GENERIC_FORMAT)
00196 fprintf(ofp, " PFD_GENERIC_FORMAT\n"); 
00197 } 
00198 if (ofp != NULL && ofp != stdout) 
00199 fclose(ofp);
00200 }
00201 #endif
00202 
00203 static HGLRC SetupOpenGL(wgldata *glwsrv) {
00204 int ID;
00205 HDC hDC;
00206 HGLRC hRC;
00207 
00208 PIXELFORMATDESCRIPTOR pfd = {
00209 sizeof (PIXELFORMATDESCRIPTOR), /* struct size */
00210 1, /* Version number */
00211 PFD_DRAW_TO_WINDOW /* Flags, draw to a window, */
00212 | PFD_DOUBLEBUFFER /* Requires Doublebuffer hw */
00213 | PFD_STEREO /* we want stereo if possible */ 
00214 | PFD_SUPPORT_OPENGL, /* use OpenGL */
00215 PFD_TYPE_RGBA, /* RGBA pixel values */
00216 16, /* 24-bit color */
00217 0, 0, 0, /* RGB bits & shift sizes. */
00218 0, 0, 0, /* Don't care about them */
00219 0, 0, /* No alpha buffer info */
00220 0, 0, 0, 0, 0, /* No accumulation buffer */
00221 16, /* depth buffer */
00222 1, /* stencil buffer */
00223 0, /* No auxiliary buffers */
00224 PFD_MAIN_PLANE, /* Layer type */
00225 0, /* Reserved (must be 0) */
00226 0, /* No layer mask */
00227 0, /* No visible mask */
00228 0 /* No damage mask */
00229 };
00230 
00231 hDC = GetDC(glwsrv->hWnd);
00232 ID = ChoosePixelFormat(hDC, &pfd);
00233 
00234 /*
00235 * catch errors here.
00236 * If ID is zero, then there's
00237 * something wrong... most likely the window's
00238 * style bits are incorrect (in CreateWindow() )
00239 * or OpenGL isn't installed on this machine
00240 */
00241 
00242 if (ID == 0) {
00243 printf("Error selecting OpenGL Pixel Format!!\n");
00244 return NULL;
00245 }
00246 
00247 glwsrv->PFDisStereo = PFDHasStereo(ID, hDC);
00248 //PrintPFD(ID, hDC);
00249 //printf("*** Setting Windows OpenGL Pixel Format to ID %d ***\n", ID); 
00250 SetPixelFormat( hDC, ID, &pfd );
00251 
00252 hRC = wglCreateContext(hDC);
00253 ReleaseDC(glwsrv->hWnd, hDC);
00254 
00255 return hRC;
00256 }
00257 
00258 static int myCreateWindow(OpenGLDisplayDevice *ogldispdev,
00259 int xpos, int ypos, int xs, int ys) {
00260 /* Create a main window for this application instance. */
00261 ogldispdev->glwsrv.hWnd =
00262 CreateWindow(
00263 szAppName, /* app name */
00264 szAppTitle, /* Text for window title bar */
00265 WS_OVERLAPPEDWINDOW /* Window style */
00266 | WS_CLIPCHILDREN
00267 | WS_CLIPSIBLINGS, /* NEED THESE for OpenGL calls to work! */
00268 xpos, ypos,
00269 xs, ys,
00270 NULL, /* no parent window */
00271 NULL, /* Use the window class menu. */
00272 GetModuleHandle(NULL), /* This instance owns this window */
00273 ogldispdev /* We pass in the caller class ptr */
00274 );
00275 
00276 if (!ogldispdev->glwsrv.hWnd) {
00277 printf("Couldn't Open Window!!\n");
00278 return -1;
00279 }
00280 
00281 ogldispdev->glwsrv.hDC = GetDC(ogldispdev->glwsrv.hWnd);
00282 wglMakeCurrent(ogldispdev->glwsrv.hDC, ogldispdev->glwsrv.hRC);
00283 
00284 /* Make the window visible & update its client area */
00285 ShowWindow(ogldispdev->glwsrv.hWnd, SW_SHOW); /* Show the window */
00286 UpdateWindow(ogldispdev->glwsrv.hWnd ); /* Sends WM_PAINT msg */
00287 DragAcceptFiles(ogldispdev->glwsrv.hWnd, TRUE); /* Enable Drag & Drop */
00288 
00289 return 0;
00290 }
00291 
00292 static void vmd_transwin32mouse(OpenGLDisplayDevice * d, LPARAM l) {
00293 int x, y;
00294 x = LOWORD(l);
00295 y = HIWORD(l);
00296 if(x & 1 << 15) x -= (1 << 16); // handle mouse capture in negative range
00297 if(y & 1 << 15) y -= (1 << 16); // handle mouse capture in negative range
00298 d->glwsrv.MouseX = x;
00299 d->glwsrv.MouseY = (d->ySize) - y; // translate to coords VMD likes (GL-like)
00300 }
00301 
00302 
00303 #ifdef VMDSPACEWARE
00304 // Windows code to talk to Spaceball device
00305 static void vmd_setupwin32spaceball(wgldata *glwsrv) {
00306 SiOpenData oData;
00307 enum SpwRetVal res;
00308 
00309 // init the sball pointer to NULL by default, used to determine if we
00310 // had a healthy init later on.
00311 glwsrv->sball = NULL;
00312 
00313 switch (SiInitialize()) {
00314 case SPW_NO_ERROR:
00315 break;
00316 
00317 case SPW_DLL_LOAD_ERROR:
00318 msgInfo << "Spaceball driver not installed. Spaceball interface disabled." << sendmsg;
00319 return;
00320 
00321 default:
00322 msgInfo << "Spaceball did not initialize properly. Spaceball interface disabled." << sendmsg;
00323 return;
00324 }
00325 
00326 SiOpenWinInit(&oData, glwsrv->hWnd); // init win platform data
00327 SiSetUiMode(glwsrv->sball, SI_UI_ALL_CONTROLS); // config softbutton display
00328 
00329 // actually start a connection to the device now that the UI mode
00330 // and window system data are setup.
00331 glwsrv->sball = SiOpen("VMD", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
00332 if ((glwsrv->sball == NULL) || (glwsrv->sball == SI_NO_HANDLE)) {
00333 SiTerminate(); // shutdown spaceware input library
00334 msgInfo << "Spaceball is unresponsive. Spaceball interface disabled." << sendmsg;
00335 glwsrv->sball = NULL; // NULL out the handle for sure.
00336 return;
00337 }
00338 
00339 res = SiBeep(glwsrv->sball, "CcCc"); // beep the spaceball
00340 if ((glwsrv->sball != NULL) && (glwsrv->sball != SI_NO_HANDLE))
00341 msgInfo << "Spaceball found, software interface initialized." << sendmsg;
00342 }
00343 
00344 static void vmd_closewin32spaceball(wgldata *glwsrv) {
00345 enum SpwRetVal res;
00346 
00347 if (glwsrv->sball != NULL) {
00348 res = SiClose(glwsrv->sball); // close spaceball device
00349 if (res != SPW_NO_ERROR) 
00350 msgInfo << "An error occured while shutting down the Spaceball device." << sendmsg;
00351 
00352 SiTerminate(); // shutdown spaceware input library
00353 }
00354 
00355 glwsrv->sball = NULL; // NULL out the handle.
00356 }
00357 
00358 static int vmd_processwin32spaceballevent(wgldata *glwsrv, UINT msg, WPARAM wParam, LPARAM lParam) {
00359 
00360 if (glwsrv == NULL)
00361 return 0;
00362 
00363 if (glwsrv->sball == NULL) 
00364 return 0; // no spaceball attached/running
00365 
00366 // Check to see if this message is a spaceball message
00367 SiGetEventWinInit(&glwsrv->spwedata, msg, wParam, lParam);
00368 
00369 if (SiGetEvent(glwsrv->sball, 0, &glwsrv->spwedata, &glwsrv->spwevent) == SI_IS_EVENT) {
00370 return 1;
00371 }
00372 
00373 return 0;
00374 }
00375 #endif
00376 
00377 
00378 LRESULT WINAPI vmdWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
00379 PAINTSTRUCT ps; /* Paint structure. */
00380 
00381 // XXX this enum has to be replicated here since its otherwise 
00382 // private to the DisplayDevice class and children.
00383 enum EventCodes { WIN_REDRAW, WIN_LEFT, WIN_MIDDLE, WIN_RIGHT,
00384 WIN_WHEELUP, WIN_WHEELDOWN, WIN_MOUSEX, WIN_MOUSEY, 
00385 WIN_KBD, 
00386 WIN_KBD_ESCAPE,
00387 WIN_KBD_UP,
00388 WIN_KBD_DOWN,
00389 WIN_KBD_LEFT,
00390 WIN_KBD_RIGHT,
00391 WIN_KBD_PAGE_UP,
00392 WIN_KBD_PAGE_DOWN,
00393 WIN_KBD_HOME,
00394 WIN_KBD_END,
00395 WIN_KBD_INSERT,
00396 WIN_KBD_DELETE,
00397 WIN_KBD_F1, WIN_KBD_F2, WIN_KBD_F3, WIN_KBD_F4,
00398 WIN_KBD_F5, WIN_KBD_F6, WIN_KBD_F7, WIN_KBD_F8,
00399 WIN_KBD_F9, WIN_KBD_F10, WIN_KBD_F11, WIN_KBD_F12,
00400 WIN_NOEVENT };
00401 wgldata *glwsrv;
00402 OpenGLDisplayDevice * ogldispdev;
00403 
00404 // Upon first window creation, immediately set our user-data field
00405 // to store caller-provided handles for this window instance
00406 if (msg == WM_NCCREATE) {
00407 #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64)
00408 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) (((CREATESTRUCT *) lParam)->lpCreateParams));
00409 #else
00410 SetWindowLong(hwnd, GWL_USERDATA, (LONG) (((CREATESTRUCT *) lParam)->lpCreateParams));
00411 #endif
00412 }
00413 
00414 // check to make sure we have a valid window data structure in case
00415 // it is destroyed while there are still pending messages...
00416 #if defined(_M_X64) || defined(_WIN64) || defined(_Wp64)
00417 ogldispdev = (OpenGLDisplayDevice *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
00418 #else
00419 ogldispdev = (OpenGLDisplayDevice *) GetWindowLong(hwnd, GWL_USERDATA);
00420 #endif
00421 
00422 // when VMD destroys its window data structures it is possible that
00423 // the window could still get messages briefly thereafter, this prevents
00424 // us from attempting to handle any messages when the VMD state that goes
00425 // with the window has already been destructed. (most notably when using
00426 // the spaceball..) If we have a NULL pointer, let windows handle the
00427 // event for us using the default window proc.
00428 if (ogldispdev == NULL)
00429 return DefWindowProc(hwnd, msg, wParam, lParam);
00430 
00431 glwsrv = &ogldispdev->glwsrv;
00432 
00433 #ifdef VMDSPACEWARE
00434 // see if it is a spaceball event, if so do something about it.
00435 if (vmd_processwin32spaceballevent(glwsrv, msg, wParam, lParam))
00436 return 0; //
00437 #endif
00438 
00439 switch(msg) {
00440 case WM_CREATE:
00441 glwsrv->hWnd = hwnd;
00442 glwsrv->hRC = SetupOpenGL(glwsrv);
00443 glwsrv->WEvents = WIN_REDRAW;
00444 return 0;
00445 
00446 case WM_SIZE:
00447 wglMakeCurrent(glwsrv->hDC, glwsrv->hRC);
00448 ogldispdev->xSize = LOWORD(lParam);
00449 ogldispdev->ySize = HIWORD(lParam);
00450 ogldispdev->reshape();
00451 glViewport(0, 0, (GLsizei) ogldispdev->xSize, (GLsizei) ogldispdev->ySize);
00452 glwsrv->WEvents = WIN_REDRAW;
00453 return 0;
00454 
00455 case WM_SIZING:
00456 wglMakeCurrent(glwsrv->hDC, glwsrv->hRC);
00457 glClear(GL_COLOR_BUFFER_BIT);
00458 SwapBuffers(glwsrv->hDC);
00459 glDrawBuffer(GL_BACK);
00460 return 0;
00461 
00462 case WM_CLOSE:
00463 PostQuitMessage(0);
00464 return 0;
00465 
00466 case WM_PAINT:
00467 BeginPaint(hwnd, &ps);
00468 EndPaint(hwnd, &ps);
00469 glwsrv->WEvents = WIN_REDRAW;
00470 return 0;
00471 
00472 case WM_KEYDOWN:
00473 glwsrv->KeyFlag = MapVirtualKey((UINT) wParam, 2); // map to ASCII
00474 glwsrv->WEvents = WIN_KBD;
00475 if (glwsrv->KeyFlag == 0) {
00476 unsigned int keysym = (unsigned int) wParam;
00477 switch (keysym) {
00478 case VK_ESCAPE: glwsrv->WEvents = WIN_KBD_ESCAPE; break;
00479 case VK_UP: glwsrv->WEvents = WIN_KBD_UP; break;
00480 case VK_DOWN: glwsrv->WEvents = WIN_KBD_DOWN; break;
00481 case VK_LEFT: glwsrv->WEvents = WIN_KBD_LEFT; break;
00482 case VK_RIGHT: glwsrv->WEvents = WIN_KBD_RIGHT; break;
00483 case VK_PRIOR: glwsrv->WEvents = WIN_KBD_PAGE_UP; break;
00484 case VK_NEXT: glwsrv->WEvents = WIN_KBD_PAGE_DOWN; break;
00485 case VK_HOME: glwsrv->WEvents = WIN_KBD_HOME; break;
00486 case VK_END: glwsrv->WEvents = WIN_KBD_END; break;
00487 case VK_INSERT: glwsrv->WEvents = WIN_KBD_INSERT; break;
00488 case VK_DELETE: glwsrv->WEvents = WIN_KBD_DELETE; break;
00489 case VK_F1: glwsrv->WEvents = WIN_KBD_F1; break;
00490 case VK_F2: glwsrv->WEvents = WIN_KBD_F2; break;
00491 case VK_F3: glwsrv->WEvents = WIN_KBD_F3; break;
00492 case VK_F4: glwsrv->WEvents = WIN_KBD_F4; break;
00493 case VK_F5: glwsrv->WEvents = WIN_KBD_F5; break;
00494 case VK_F6: glwsrv->WEvents = WIN_KBD_F6; break;
00495 case VK_F7: glwsrv->WEvents = WIN_KBD_F7; break;
00496 case VK_F8: glwsrv->WEvents = WIN_KBD_F8; break;
00497 case VK_F9: glwsrv->WEvents = WIN_KBD_F9; break;
00498 case VK_F10: glwsrv->WEvents = WIN_KBD_F10; break;
00499 case VK_F11: glwsrv->WEvents = WIN_KBD_F11; break;
00500 case VK_F12: glwsrv->WEvents = WIN_KBD_F12; break;
00501 default:
00502 glwsrv->WEvents = WIN_NOEVENT;
00503 break;
00504 }
00505 }
00506 return 0;
00507 
00508 case WM_MOUSEMOVE:
00509 vmd_transwin32mouse(ogldispdev, lParam);
00510 glwsrv->MouseFlags = (long) wParam;
00511 return 0;
00512 
00513 case WM_MOUSEWHEEL:
00514 {
00515 int zDelta = ((short) HIWORD(wParam));
00516 // XXX
00517 // zDelta is in positive or negative multiples of WHEEL_DELTA for
00518 // clicky type scroll wheels on existing mice, may need to
00519 // recode this for continuous wheels at some future point in time.
00520 // WHEEL_DELTA is 120 in current versions of Windows.
00521 // We only activate an event if the user moves the mouse wheel at
00522 // least half of WHEEL_DELTA, so that they don't do it by accident
00523 // all the time.
00524 if (zDelta > (WHEEL_DELTA / 2)) {
00525 glwsrv->WEvents = WIN_WHEELUP;
00526 } else if (zDelta < -(WHEEL_DELTA / 2)) {
00527 glwsrv->WEvents = WIN_WHEELDOWN;
00528 }
00529 }
00530 return 0;
00531 
00532 case WM_LBUTTONDOWN:
00533 SetCapture(hwnd);
00534 vmd_transwin32mouse(ogldispdev, lParam);
00535 glwsrv->MouseFlags = (long) wParam;
00536 glwsrv->WEvents = WIN_LEFT;
00537 return 0;
00538 
00539 case WM_LBUTTONUP:
00540 vmd_transwin32mouse(ogldispdev, lParam);
00541 glwsrv->MouseFlags = (long) wParam;
00542 glwsrv->WEvents = WIN_LEFT;
00543 if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00544 ReleaseCapture();
00545 return 0;
00546 
00547 case WM_MBUTTONDOWN:
00548 SetCapture(hwnd);
00549 vmd_transwin32mouse(ogldispdev, lParam);
00550 glwsrv->MouseFlags = (long) wParam;
00551 glwsrv->WEvents = WIN_MIDDLE;
00552 return 0;
00553 
00554 case WM_MBUTTONUP:
00555 vmd_transwin32mouse(ogldispdev, lParam);
00556 glwsrv->MouseFlags = (long) wParam;
00557 glwsrv->WEvents = WIN_MIDDLE;
00558 if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00559 ReleaseCapture();
00560 return 0;
00561 
00562 case WM_RBUTTONDOWN:
00563 SetCapture(hwnd);
00564 vmd_transwin32mouse(ogldispdev, lParam);
00565 glwsrv->MouseFlags = (long) wParam;
00566 glwsrv->WEvents = WIN_RIGHT;
00567 return 0;
00568 
00569 case WM_RBUTTONUP:
00570 vmd_transwin32mouse(ogldispdev, lParam);
00571 glwsrv->MouseFlags = (long) wParam;
00572 glwsrv->WEvents = WIN_RIGHT;
00573 if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00574 ReleaseCapture();
00575 return 0;
00576 
00577 case WM_SETCURSOR:
00578 // We process the mouse cursor hit test codes here, they tell us
00579 // what part of the window we're over, which helps us set the cursor
00580 // to the correct style for sizing borders, moves, etc.
00581 switch (LOWORD(lParam)) {
00582 case HTBOTTOM:
00583 case HTTOP:
00584 SetCursor(LoadCursor(NULL, IDC_SIZENS));
00585 break;
00586 
00587 case HTLEFT:
00588 case HTRIGHT:
00589 SetCursor(LoadCursor(NULL, IDC_SIZEWE));
00590 break;
00591 
00592 case HTTOPRIGHT:
00593 case HTBOTTOMLEFT:
00594 SetCursor(LoadCursor(NULL, IDC_SIZENESW));
00595 break;
00596 
00597 case HTTOPLEFT:
00598 case HTBOTTOMRIGHT:
00599 SetCursor(LoadCursor(NULL, IDC_SIZENWSE));
00600 break;
00601 
00602 case HTCAPTION:
00603 SetCursor(LoadCursor(NULL, IDC_ARROW));
00604 break;
00605 
00606 case HTCLIENT:
00607 default:
00608 ogldispdev->set_cursor(glwsrv->cursornum);
00609 }
00610 return 0;
00611 
00612 // 
00613 // Handle Windows File Drag and Drop Operations 
00614 // This code needs to be linked against SHELL32.DLL
00615 // 
00616 case WM_DROPFILES: 
00617 {
00618 char lpszFile[4096];
00619 UINT numfiles, fileindex, numc;
00620 HDROP hDropInfo = (HDROP)wParam;
00621 
00622 // Get the number of simultaneous dragged/dropped files.
00623 numfiles = DragQueryFile(hDropInfo, (DWORD)(-1), (LPSTR)NULL, 0);
00624 
00625 msgInfo << "Ignoring Drag and Drop operation, received " 
00626 << ((int) numfiles) << " files:" << sendmsg;
00627 
00628 FileSpec spec; 
00629 for (fileindex=0; fileindex<numfiles; fileindex++) {
00630 // lpszFile: complete pathname with device, colon and backslashes
00631 numc = DragQueryFile(hDropInfo, fileindex, (char *) &lpszFile, 4096);
00632 
00633 // VMD loads the file(s) here, or queues them up in its own
00634 // list to decide how to cope with them. Deciding how to deal
00635 // with these files is definitely the tricky part.
00636 msgInfo << " File(" << ((int) fileindex) << "): " << lpszFile 
00637 << " (numc=" << ((int) numc) << ")" << sendmsg;
00638 
00639 // attempt to load the file into a new molecule
00640 ogldispdev->vmdapp->molecule_load(-1, lpszFile, NULL, &spec);
00641 } 
00642 DragFinish(hDropInfo); // finish drop operation and release memory
00643 }
00644 return 0;
00645 
00646 default:
00647 return DefWindowProc(hwnd, msg, wParam, lParam);
00648 }
00649 
00650 return 0;
00651 }
00652 
00653 
00655 
00656 OpenGLDisplayDevice::OpenGLDisplayDevice() 
00657 : OpenGLRenderer("VMD " VMDVERSION " OpenGL Display") {
00658 // set up data possible before opening window
00659 stereoNames = glStereoNameStr;
00660 stereoModes = OPENGL_STEREO_MODES;
00661 
00662 renderNames = glRenderNameStr;
00663 renderModes = OPENGL_RENDER_MODES;
00664 
00665 cacheNames = glCacheNameStr;
00666 cacheModes = OPENGL_CACHE_MODES;
00667 
00668 memset(&glwsrv, 0, sizeof(glwsrv));
00669 have_window = FALSE;
00670 screenX = screenY = 0;
00671 vmdapp = NULL;
00672 }
00673 
00674 // init ... open a window and set initial default values
00675 int OpenGLDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
00676 vmdapp = app; // save VMDApp handle for use by drag-and-drop handlers
00677 
00678 // open the window
00679 if (open_window(name, size, loc, argc, argv) != 0) return FALSE;
00680 if (!have_window) return FALSE;
00681 
00682 // get screen size 
00683 // XXX There's no Win32 API to get the full multi-monitor desktop,
00684 // so this code doesn't correctly handle multi-monitor systems yet.
00685 // To correctly handle multiple monitors, we'd have to 
00686 // walk the device tree, take into account monitor layout/positioning, 
00687 // and compute the desktop dimensions from that. Since these values
00688 // are currently only used by do_reposition_window() method, we can
00689 // live with primary-monitor values for the time being.
00690 screenX = GetSystemMetrics(SM_CXSCREEN);
00691 screenY = GetSystemMetrics(SM_CYSCREEN);
00692 
00693 // set flags for the capabilities of this display
00694 ext->hasmultisample = FALSE; // no code for this extension yet
00695 ext->nummultisamples = 0;
00696 aaAvailable = FALSE;
00697 
00698 // set default settings
00699 if (ext->hasmultisample) {
00700 aa_on(); // enable fast multisample based antialiasing by default
00701 // other antialiasing techniques are slow, so only multisample
00702 // makes sense to enable by default.
00703 }
00704 
00705 cueingAvailable = TRUE;
00706 cueing_on(); // leave depth cueing on by default, despite the speed hit.
00707 
00708 cullingAvailable = TRUE;
00709 culling_off();
00710 
00711 set_sphere_mode(sphereMode);
00712 set_sphere_res(sphereRes);
00713 set_line_width(lineWidth);
00714 set_line_style(lineStyle);
00715 
00716 // reshape and clear the display, which initializes some other variables
00717 reshape();
00718 normal();
00719 clear();
00720 update();
00721 
00722 // successfully created window
00723 return TRUE;
00724 }
00725 
00726 // destructor ... close the window
00727 OpenGLDisplayDevice::~OpenGLDisplayDevice(void) {
00728 if (have_window) {
00729 // close and delete windows, contexts, and display connections
00730 free_opengl_ctx(); // free display lists, textures, etc
00731 
00732 #if VMDSPACEWARE
00733 vmd_closewin32spaceball(&glwsrv);
00734 #endif
00735 }
00736 }
00737 
00738 
00740 
00741 // create a new window and set it's characteristics
00742 int OpenGLDisplayDevice::open_window(char *nm, int *size, int *loc,
00743 int argc, char** argv) {
00744 int SX = 596, SY = 190;
00745 if (loc) {
00746 SX = loc[0];
00747 // X screen uses Y increasing from upper-left corner down; this is
00748 // opposite to what GL does, which is the way VMD was set up originally
00749 SY = screenY - loc[1] - size[1];
00750 }
00751 glwsrv.cursornum = 0; // initialize cursor number
00752 
00753 // window opening stuff goes here
00754 int rc = OpenWin32Connection(&glwsrv);
00755 if (rc != 0) {
00756 return -1;
00757 }
00758 
00759 xOrig = 0;
00760 yOrig = 0;
00761 xSize = size[0]; 
00762 ySize = size[1]; 
00763 glwsrv.width = xSize; 
00764 glwsrv.height = ySize; 
00765 rc = myCreateWindow(this, 0, 0, glwsrv.width, glwsrv.height);
00766 if (rc != 0) {
00767 return -1;
00768 }
00769 
00770 // Determine if stereo is available
00771 if (glwsrv.PFDisStereo == 0) {
00772 ext->hasstereo = FALSE;
00773 } else {
00774 ext->hasstereo = TRUE;
00775 }
00776 ext->stereodrawforced = FALSE; // don't force stereo draws initially
00777 
00778 setup_initial_opengl_state();
00779 
00780 #ifdef VMDSPACEWARE
00781 vmd_setupwin32spaceball(&glwsrv); 
00782 #endif
00783 
00784 // normal return: window was successfully created
00785 have_window = TRUE;
00786 // return window id
00787 return 0;
00788 }
00789 
00790 
00791 int OpenGLDisplayDevice::prepare3D(int do_clear) {
00792 // force reset of OpenGL context back to ours in case something
00793 // else modified the OpenGL state
00794 wglMakeCurrent(glwsrv.hDC, glwsrv.hRC);
00795 
00796 return OpenGLRenderer::prepare3D(do_clear);
00797 }
00798 
00799 void OpenGLDisplayDevice::do_resize_window(int width, int height) {
00800 RECT rcClient, rcWindow;
00801 POINT ptDiff;
00802 GetClientRect(glwsrv.hWnd, &rcClient);
00803 GetWindowRect(glwsrv.hWnd, &rcWindow);
00804 ptDiff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
00805 ptDiff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
00806 MoveWindow(glwsrv.hWnd, rcWindow.left, rcWindow.top, width + ptDiff.x, height + ptDiff.y, TRUE);
00807 }
00808 
00809 void OpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
00810 RECT rcClient, rcWindow;
00811 GetClientRect(glwsrv.hWnd, &rcClient);
00812 GetWindowRect(glwsrv.hWnd, &rcWindow);
00813 MoveWindow(glwsrv.hWnd, xpos, ypos, rcWindow.right-rcWindow.left, rcWindow.bottom-rcWindow.top, TRUE);
00814 }
00815 
00816 
00818 
00819 //
00820 // get the current state of the device's pointer (i.e. cursor if it has one)
00821 //
00822 
00823 // abs X pos of cursor from lower-left corner of display
00824 int OpenGLDisplayDevice::x(void) {
00825 return glwsrv.MouseX;
00826 }
00827 
00828 // same, for Y direction
00829 int OpenGLDisplayDevice::y(void) {
00830 return glwsrv.MouseY;
00831 }
00832 
00833 // return the current state of the shift, control, and alt keys
00834 int OpenGLDisplayDevice::shift_state(void) {
00835 int retval = 0;
00836 
00837 if ((glwsrv.MouseFlags & MK_SHIFT) != 0)
00838 retval |= SHIFT;
00839 
00840 if ((glwsrv.MouseFlags & MK_CONTROL) != 0)
00841 retval |= CONTROL;
00842 
00843 return retval; 
00844 }
00845 
00846 // return the spaceball state, if any
00847 int OpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty, int *tz, int *buttons) {
00848 
00849 #ifdef VMDSPACEWARE
00850 if (glwsrv.sball != NULL) {
00851 *rx = glwsrv.spwevent.u.spwData.mData[SI_RX];
00852 *ry = glwsrv.spwevent.u.spwData.mData[SI_RY];
00853 *rz = glwsrv.spwevent.u.spwData.mData[SI_RZ];
00854 *tx = glwsrv.spwevent.u.spwData.mData[SI_TX];
00855 *ty = glwsrv.spwevent.u.spwData.mData[SI_TY];
00856 *tz = glwsrv.spwevent.u.spwData.mData[SI_TZ];
00857 *buttons = glwsrv.spwevent.u.spwData.bData.current;
00858 return 1;
00859 }
00860 #endif
00861 
00862 return 0;
00863 }
00864 
00865 
00866 // set the Nth cursor shape as the current one.
00867 void OpenGLDisplayDevice::set_cursor(int n) {
00868 glwsrv.cursornum = n; // hack to save cursor state when mouse enters/leaves
00869 
00870 switch (n) {
00871 default:
00872 case DisplayDevice::NORMAL_CURSOR:
00873 SetCursor(LoadCursor(NULL, IDC_ARROW));
00874 break;
00875 
00876 case DisplayDevice::TRANS_CURSOR:
00877 SetCursor(LoadCursor(NULL, IDC_SIZEALL));
00878 break;
00879 
00880 case DisplayDevice::SCALE_CURSOR:
00881 SetCursor(LoadCursor(NULL, IDC_SIZEWE));
00882 break;
00883 
00884 case DisplayDevice::PICK_CURSOR:
00885 SetCursor(LoadCursor(NULL, IDC_CROSS));
00886 break;
00887 
00888 case DisplayDevice::WAIT_CURSOR:
00889 SetCursor(LoadCursor(NULL, IDC_WAIT));
00890 break;
00891 }
00892 }
00893 
00894 
00895 //
00896 // event handling routines
00897 //
00898 
00899 // queue the standard events (need only be called once ... but this is
00900 // not done automatically by the window because it may not be necessary or
00901 // even wanted)
00902 void OpenGLDisplayDevice::queue_events(void) {
00903 }
00904 
00905 // read the next event ... returns an event type (one of the above ones),
00906 // and a value. Returns success, and sets arguments.
00907 int OpenGLDisplayDevice::read_event(long &retdev, long &retval) {
00908 MSG msg;
00909 
00910 // This pumps the Windows message queue, forcing WEvents to be updated
00911 // by the time we return from DispatchMessage.
00912 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
00913 TranslateMessage(&msg); // translate the message
00914 DispatchMessage(&msg); // fire it off to the window proc
00915 } 
00916 
00917 retdev = glwsrv.WEvents;
00918 
00919 switch (glwsrv.WEvents) {
00920 case WIN_REDRAW:
00921 glwsrv.WEvents = WIN_NOEVENT;
00922 // reshape() is already called from within the window proc.
00923 _needRedraw = 1;
00924 return FALSE;
00925 
00926 case WIN_KBD:
00927 if (glwsrv.KeyFlag != '0円') {
00928 retval = glwsrv.KeyFlag;
00929 glwsrv.WEvents = WIN_NOEVENT;
00930 return TRUE;
00931 }
00932 break; 
00933 
00934 case WIN_KBD_ESCAPE:
00935 case WIN_KBD_UP:
00936 case WIN_KBD_DOWN:
00937 case WIN_KBD_LEFT:
00938 case WIN_KBD_RIGHT:
00939 case WIN_KBD_PAGE_UP:
00940 case WIN_KBD_PAGE_DOWN:
00941 case WIN_KBD_HOME:
00942 case WIN_KBD_END:
00943 case WIN_KBD_INSERT:
00944 case WIN_KBD_DELETE:
00945 case WIN_KBD_F1:
00946 case WIN_KBD_F2:
00947 case WIN_KBD_F3:
00948 case WIN_KBD_F4:
00949 case WIN_KBD_F5:
00950 case WIN_KBD_F6:
00951 case WIN_KBD_F7:
00952 case WIN_KBD_F8:
00953 case WIN_KBD_F9:
00954 case WIN_KBD_F10:
00955 case WIN_KBD_F11:
00956 case WIN_KBD_F12:
00957 retval = glwsrv.KeyFlag;
00958 glwsrv.WEvents = WIN_NOEVENT;
00959 return TRUE;
00960 
00961 case WIN_WHEELUP:
00962 retval = 1;
00963 glwsrv.WEvents = WIN_NOEVENT;
00964 return TRUE;
00965 
00966 case WIN_WHEELDOWN:
00967 retval = 1;
00968 glwsrv.WEvents = WIN_NOEVENT;
00969 return TRUE;
00970 
00971 case WIN_LEFT:
00972 // retval _must_ be either 1 or 0, nothing else...
00973 retval = (glwsrv.MouseFlags & MK_LBUTTON) != 0; 
00974 glwsrv.WEvents = WIN_NOEVENT;
00975 return TRUE;
00976 
00977 case WIN_MIDDLE:
00978 // retval _must_ be either 1 or 0, nothing else...
00979 retval = (glwsrv.MouseFlags & MK_MBUTTON) != 0; 
00980 glwsrv.WEvents = WIN_NOEVENT;
00981 return TRUE;
00982 
00983 case WIN_RIGHT:
00984 // retval _must_ be either 1 or 0, nothing else...
00985 retval = (glwsrv.MouseFlags & MK_RBUTTON) != 0; 
00986 glwsrv.WEvents = WIN_NOEVENT;
00987 return TRUE;
00988 }
00989 
00990 retval = 0; 
00991 glwsrv.WEvents = WIN_NOEVENT;
00992 return FALSE;
00993 }
00994 
00995 
00996 //
00997 // virtual routines for preparing to draw, drawing, and finishing drawing
00998 //
00999 
01000 // reshape the display after a shape change
01001 void OpenGLDisplayDevice::reshape(void) {
01002 // this code assumes that the xSize and ySize variables have
01003 // been updated (magically) already by the time this gets called.
01004 
01005 switch (inStereo) {
01006 case OPENGL_STEREO_SIDE:
01007 set_screen_pos(0.5f * (float)xSize / (float)ySize);
01008 break;
01009 
01010 case OPENGL_STEREO_ABOVEBELOW:
01011 set_screen_pos(2.0f * (float)xSize / (float)ySize);
01012 break;
01013 
01014 case OPENGL_STEREO_STENCIL_CHECKERBOARD:
01015 case OPENGL_STEREO_STENCIL_COLUMNS:
01016 case OPENGL_STEREO_STENCIL_ROWS:
01017 enable_stencil_stereo(inStereo);
01018 set_screen_pos((float)xSize / (float)ySize);
01019 break;
01020 
01021 default:
01022 set_screen_pos((float)xSize / (float)ySize);
01023 break;
01024 }
01025 }
01026 
01027 unsigned char * OpenGLDisplayDevice::readpixels_rgb3u(int &x, int &y) {
01028 unsigned char * img;
01029 
01030 x = xSize;
01031 y = ySize;
01032 
01033 if ((img = (unsigned char *) malloc(x * y * 3)) != NULL) {
01034 glPixelStorei(GL_PACK_ALIGNMENT, 1);
01035 glReadPixels(0, 0, x, y, GL_RGB, GL_UNSIGNED_BYTE, img);
01036 } else {
01037 x = 0;
01038 y = 0;
01039 } 
01040 
01041 return img; 
01042 }
01043 
01044 
01045 unsigned char * OpenGLDisplayDevice::readpixels_rgba4u(int &xs, int &ys) {
01046 unsigned char * img = NULL;
01047 xs = xSize;
01048 ys = ySize;
01049 
01050 // fall back to normal glReadPixels() if better methods fail
01051 if ((img = (unsigned char *) malloc(xs * ys * 4)) != NULL) {
01052 glPixelStorei(GL_PACK_ALIGNMENT, 1);
01053 glReadPixels(0, 0, xs, ys, GL_RGBA, GL_UNSIGNED_BYTE, img);
01054 return img;
01055 }
01056 
01057 // else bail out
01058 xs = 0;
01059 ys = 0;
01060 return NULL;
01061 }
01062 
01063 
01064 int OpenGLDisplayDevice::drawpixels_rgba4u(unsigned char *rgba, int &xs, int &ys) {
01065 
01066 #if 0
01067 // glDrawBuffer(GL_BACK);
01068 // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01069 // glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
01070 // glClear(GL_COLOR_BUFFER_BIT);
01071 
01072 glPushMatrix();
01073 glDisable(GL_DEPTH_TEST);
01074 
01075 glViewport(0, 0, xs, ys);
01076 
01077 glShadeModel(GL_FLAT);
01078 glMatrixMode(GL_PROJECTION);
01079 glLoadIdentity();
01080 glOrtho(0.0, xs, 0.0, ys, -1.0, 1.0);
01081 glMatrixMode(GL_MODELVIEW);
01082 glLoadIdentity();
01083 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01084 glPixelZoom(1.0, 1.0);
01085 
01086 glRasterPos2i(0, 0);
01087 glDrawPixels(xs, ys, GL_RGBA, GL_UNSIGNED_BYTE, rgba);
01088 
01089 glEnable(GL_DEPTH_TEST);
01090 glPopMatrix();
01091 #elif 1
01092 // glDrawBuffer(GL_BACK);
01093 // glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
01094 // glClearColor(0.0, 0.0, 0.0, 1.0); /* black */
01095 // glClear(GL_COLOR_BUFFER_BIT);
01096 
01097 glPushMatrix();
01098 glDisable(GL_DEPTH_TEST);
01099 
01100 glViewport(0, 0, xs, ys);
01101 
01102 glShadeModel(GL_FLAT);
01103 glMatrixMode(GL_PROJECTION);
01104 glLoadIdentity();
01105 glOrtho(0.0, xs, 0.0, ys, -1.0, 1.0);
01106 glMatrixMode(GL_MODELVIEW);
01107 
01108 GLuint texName = 0;
01109 GLfloat texborder[4] = {0.0, 0.0, 0.0, 1.0};
01110 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01111 glBindTexture(GL_TEXTURE_2D, texName);
01112 
01113 /* black borders if we go rendering anything beyond texture coordinates */
01114 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, texborder);
01115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
01116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
01117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01119 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
01120 
01121 glLoadIdentity();
01122 glColor3f(1.0, 1.0, 1.0);
01123 
01124 #if 1
01125 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xs, ys, 0,
01126 GL_RGBA, GL_UNSIGNED_BYTE, rgba);
01127 glEnable(GL_TEXTURE_2D);
01128 #endif
01129 
01130 glBegin(GL_QUADS);
01131 glTexCoord2f(0.0f, 0.0f);
01132 glVertex2f(0, 0);
01133 glTexCoord2f(0.0f, 1.0f);
01134 glVertex2f(0, GLfloat(ys));
01135 glTexCoord2f(1.0f, 1.0f);
01136 glVertex2f(GLfloat(xs), GLfloat(ys));
01137 glTexCoord2f(1.0f, 0.0f);
01138 glVertex2f(GLfloat(xs), 0.0f);
01139 glEnd();
01140 
01141 #if 1
01142 glDisable(GL_TEXTURE_2D);
01143 #endif
01144 
01145 glEnable(GL_DEPTH_TEST);
01146 glPopMatrix();
01147 #endif
01148 
01149 update();
01150 
01151 return 0;
01152 }
01153 
01154 
01155 
01156 
01157 // update after drawing
01158 void OpenGLDisplayDevice::update(int do_update) {
01159 glFlush();
01160 
01161 if(do_update) 
01162 SwapBuffers(glwsrv.hDC);
01163 
01164 glDrawBuffer(GL_BACK);
01165 }
01166 
01167 
01168 void OpenGLDisplayDevice::set_window_title(char *newtitlestr) {
01169 #if defined(_MSC_VER)
01170 // not yet implemented
01171 #endif
01172 }
01173 

Generated on Mon Nov 17 02:47:29 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /