From 353af7395199a5de78e0c8478d603fc6397c6550 Mon Sep 17 00:00:00 2001 From: cxgeorge <> Date: Mon, 16 Jul 2001 22:50:29 +0000 Subject: [PATCH] handle fullscreen mode, revamp window-handling stuff --- panda/src/wgldisplay/Sources.pp | 2 +- panda/src/wgldisplay/config_wgldisplay.cxx | 9 + panda/src/wgldisplay/config_wgldisplay.h | 1 + panda/src/wgldisplay/wglGraphicsPipe.cxx | 324 +---- panda/src/wgldisplay/wglGraphicsPipe.h | 16 - panda/src/wgldisplay/wglGraphicsWindow.cxx | 1393 +++++++++++++------- panda/src/wgldisplay/wglGraphicsWindow.h | 24 +- panda/src/wgldisplay/wglext.h | 401 ++++++ 8 files changed, 1352 insertions(+), 818 deletions(-) create mode 100644 panda/src/wgldisplay/wglext.h diff --git a/panda/src/wgldisplay/Sources.pp b/panda/src/wgldisplay/Sources.pp index 3ed40da970..85005462f9 100644 --- a/panda/src/wgldisplay/Sources.pp +++ b/panda/src/wgldisplay/Sources.pp @@ -11,7 +11,7 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx #define SOURCES \ - config_wgldisplay.h wglGraphicsPipe.h wglGraphicsWindow.cxx wglGraphicsWindow.h + config_wgldisplay.h wglGraphicsPipe.h wglGraphicsWindow.cxx wglGraphicsWindow.h wglext.h #define INCLUDED_SOURCES \ config_wgldisplay.cxx wglGraphicsPipe.cxx diff --git a/panda/src/wgldisplay/config_wgldisplay.cxx b/panda/src/wgldisplay/config_wgldisplay.cxx index 9445da0939..ab7728b9e2 100644 --- a/panda/src/wgldisplay/config_wgldisplay.cxx +++ b/panda/src/wgldisplay/config_wgldisplay.cxx @@ -29,9 +29,16 @@ ConfigureFn(config_wgldisplay) { init_libwgldisplay(); } +// Configure this true to force the rendering to sync to the video +// refresh, or false to let your frame rate go as high as it can, +// irrespective of the video refresh. (if this capability is available in the ICD) +bool gl_sync_video = config_wgldisplay.GetBool("sync-video", true); + bool gl_show_fps_meter = config_wgldisplay.GetBool("show-fps-meter", false); float gl_fps_meter_update_interval = max(0.5,config_wgldisplay.GetFloat("fps-meter-update-interval", 1.7)); +extern void AtExitFn(void); + //////////////////////////////////////////////////////////////////// // Function: init_libwgldisplay // Description: Initializes the library. This must be called at @@ -56,6 +63,8 @@ init_libwgldisplay() { GraphicsWindow::get_factory().register_factory( wglGraphicsWindow::get_class_type(), wglGraphicsWindow::make_wglGraphicsWindow); + + atexit(AtExitFn); } // cant use global var cleanly because global var static init executed after init_libwgl(), incorrectly reiniting var diff --git a/panda/src/wgldisplay/config_wgldisplay.h b/panda/src/wgldisplay/config_wgldisplay.h index 25da7f8a6b..7b51653d14 100644 --- a/panda/src/wgldisplay/config_wgldisplay.h +++ b/panda/src/wgldisplay/config_wgldisplay.h @@ -28,6 +28,7 @@ NotifyCategoryDecl(wgldisplay, EXPCL_PANDAGL, EXPTP_PANDAGL); extern Filename get_icon_filename_(); extern bool gl_show_fps_meter; extern float gl_fps_meter_update_interval; +extern bool gl_sync_video; extern EXPCL_PANDAGL void init_libwgldisplay(); diff --git a/panda/src/wgldisplay/wglGraphicsPipe.cxx b/panda/src/wgldisplay/wglGraphicsPipe.cxx index d99a288c94..b656d13a25 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.cxx +++ b/panda/src/wgldisplay/wglGraphicsPipe.cxx @@ -25,61 +25,11 @@ //////////////////////////////////////////////////////////////////// TypeHandle wglGraphicsPipe::_type_handle; -wglGraphicsPipe *global_pipe; - -#define MOUSE_ENTERED 0 -#define MOUSE_EXITED 1 +//wglGraphicsPipe *global_pipe; wglGraphicsPipe::wglGraphicsPipe(const PipeSpecifier& spec) : InteractiveGraphicsPipe(spec) -{ - // Register a standard window class - WNDCLASS wc; - HINSTANCE hinstance = GetModuleHandle(NULL); - - // Clear before filling in window structure! - memset(&wc, 0, sizeof(WNDCLASS)); - wc.style = CS_OWNDC; - wc.lpfnWndProc = (WNDPROC)static_window_proc; - wc.hInstance = hinstance; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = NULL; - wc.lpszMenuName = NULL; - wc.lpszClassName = "wglStandard"; - - string windows_icon_filename = get_icon_filename_().to_os_specific(); - - if(!windows_icon_filename.empty()) { - // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) - // if icon is more than 8bpp - wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE); - } else { - wc.hIcon = NULL; // use default app icon - } - - if (!RegisterClass(&wc)) { - wgldisplay_cat.fatal() - << "wglGraphicsPipe::construct(): could not register standard window " - << "class" << endl; - exit(0); - } - - // Register a fullscreen window class - wc.style = CS_HREDRAW | CS_VREDRAW; - wc.lpszClassName = "wglFullscreen"; - - if (!RegisterClass(&wc)) { - wgldisplay_cat.fatal() - << "wglGraphicsPipe::construct(): could not register fullscreen window " - << "class" << endl; - exit(0); - } - - _width = GetSystemMetrics(SM_CXSCREEN); - _height = GetSystemMetrics(SM_CYSCREEN); - _shift = false; - global_pipe = this; -} +{} //////////////////////////////////////////////////////////////////// // Function: wglGraphicsPipe::get_window_type @@ -133,273 +83,3 @@ wglGraphicsPipe& wglGraphicsPipe::operator=(const wglGraphicsPipe&) { << "wglGraphicsPipes should not be assigned" << endl; return *this; } - -//////////////////////////////////////////////////////////////////// -// Function: find_window -// Access: -// Description: Find the window that has the xwindow "win" in the -// window list for the pipe (if it exists) -//////////////////////////////////////////////////////////////////// -wglGraphicsWindow *wglGraphicsPipe:: -find_window(HWND win) { - int num_windows = get_num_windows(); - for (int w = 0; w < num_windows; w++) { - wglGraphicsWindow *window = DCAST(wglGraphicsWindow, get_window(w)); - if (window->_mwindow == win) - return window; - } - return NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: static_window_proc -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -LONG WINAPI wglGraphicsPipe:: -static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - return global_pipe->window_proc(hwnd, msg, wparam, lparam); -} - -//////////////////////////////////////////////////////////////////// -// Function: window_proc -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -LONG wglGraphicsPipe:: -window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - PAINTSTRUCT ps; - wglGraphicsWindow *window; - int button = -1; - int x, y, width, height; - static HCURSOR hMouseCrossIcon = NULL; - - switch (msg) { - case WM_CREATE: - hMouseCrossIcon = LoadCursor(NULL, IDC_ARROW); - SetCursor(hMouseCrossIcon); - return 0; - case WM_CLOSE: - PostQuitMessage(0); - return 0; - case WM_PAINT: - window = find_window(hwnd); - if (window) { - BeginPaint(hwnd, &ps); - EndPaint(hwnd, &ps); - } - return 0; - case WM_SYSCHAR: - case WM_CHAR: - return 0; - case WM_SYSKEYDOWN: - case WM_KEYDOWN: - window = find_window(hwnd); - if (window) { - POINT point; - window->make_current(); - GetCursorPos(&point); - ScreenToClient(hwnd, &point); - window->handle_keypress(lookup_key(wparam), point.x, point.y); - } - return 0; - case WM_SYSKEYUP: - case WM_KEYUP: - window = find_window(hwnd); - if (window) { - POINT point; - window->make_current(); - GetCursorPos(&point); - ScreenToClient(hwnd, &point); - window->handle_keyrelease(lookup_key(wparam), point.x, point.y); - } - return 0; - case WM_LBUTTONDOWN: - button = 0; - case WM_MBUTTONDOWN: - if (button < 0) - button = 1; - case WM_RBUTTONDOWN: - if (button < 0) - button = 2; - SetCapture(hwnd); - // Win32 doesn't return the same numbers as X does when the mouse - // goes beyond the upper or left side of the window - x = LOWORD(lparam); - y = HIWORD(lparam); - if (x & 1 << 15) x -= (1 << 16); - if (y & 1 << 15) y -= (1 << 16); - window = find_window(hwnd); - if (window) { - window->make_current(); - window->handle_keypress(MouseButton::button(button), x, y); - } - return 0; - case WM_LBUTTONUP: - button = 0; - case WM_MBUTTONUP: - if (button < 0) - button = 1; - case WM_RBUTTONUP: - if (button < 0) - button = 2; - ReleaseCapture(); - window = find_window(hwnd); - if (window) { - x = LOWORD(lparam); - y = HIWORD(lparam); - if (x & 1 << 15) x -= (1 << 16); - if (y & 1 << 15) y -= (1 << 16); - window->make_current(); - window->handle_keyrelease(MouseButton::button(button), x, y); - } - return 0; - case WM_MOUSEMOVE: - window = find_window(hwnd); - if (window) { - x = LOWORD(lparam); - y = HIWORD(lparam); - if (x & 1 << 15) x -= (1 << 16); - if (y & 1 << 15) y -= (1 << 16); - if (window->mouse_motion_enabled() - && wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { - window->make_current(); - window->handle_mouse_motion(x, y); - } else if (window->mouse_passive_motion_enabled() && - ((wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)) { - window->make_current(); - window->handle_mouse_motion(x, y); - } - } - return 0; - case WM_SIZE: - window = find_window(hwnd); - if (window) { - width = LOWORD(lparam); - height = HIWORD(lparam); - window->handle_reshape(width, height); - } - return 0; - -#if 0 -//this is unnecessary, just handle mouse entry - case WM_SETCURSOR: - // We need to set the cursor every time the mouse moves on Win32! - if (LOWORD(lparam) != HTCLIENT) - return DefWindowProc(hwnd, msg, wparam, lparam); - window = find_window(hwnd); - if (window) { - SetCursor(LoadCursor(NULL, IDC_ARROW)); - } - return 1; -#endif - case WM_SETFOCUS: - SetCursor(hMouseCrossIcon); - window = find_window(hwnd); - if (window) { - if (window->mouse_entry_enabled()) { - window->make_current(); - window->handle_mouse_entry(MOUSE_ENTERED); - } - } - return 0; - case WM_KILLFOCUS: - window = find_window(hwnd); - if (window) { - if (window->mouse_entry_enabled()) { - window->make_current(); - window->handle_mouse_entry(MOUSE_EXITED); - } - } - return 0; - default: - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: lookup_key -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -ButtonHandle -wglGraphicsPipe::lookup_key(WPARAM wparam) const { - switch (wparam) { - case VK_BACK: return KeyboardButton::backspace(); - case VK_TAB: return KeyboardButton::tab(); - case VK_ESCAPE: return KeyboardButton::escape(); - case VK_SPACE: return KeyboardButton::space(); - case VK_UP: return KeyboardButton::up(); - case VK_DOWN: return KeyboardButton::down(); - case VK_LEFT: return KeyboardButton::left(); - case VK_RIGHT: return KeyboardButton::right(); - case VK_PRIOR: return KeyboardButton::page_up(); - case VK_NEXT: return KeyboardButton::page_down(); - case VK_HOME: return KeyboardButton::home(); - case VK_END: return KeyboardButton::end(); - case VK_F1: return KeyboardButton::f1(); - case VK_F2: return KeyboardButton::f2(); - case VK_F3: return KeyboardButton::f3(); - case VK_F4: return KeyboardButton::f4(); - case VK_F5: return KeyboardButton::f5(); - case VK_F6: return KeyboardButton::f6(); - case VK_F7: return KeyboardButton::f7(); - case VK_F8: return KeyboardButton::f8(); - case VK_F9: return KeyboardButton::f9(); - case VK_F10: return KeyboardButton::f10(); - case VK_F11: return KeyboardButton::f11(); - case VK_F12: return KeyboardButton::f12(); - case VK_INSERT: return KeyboardButton::insert(); - case VK_DELETE: return KeyboardButton::del(); - - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - return KeyboardButton::shift(); - - case VK_CONTROL: - case VK_LCONTROL: - case VK_RCONTROL: - return KeyboardButton::control(); - - case VK_MENU: - case VK_LMENU: - case VK_RMENU: - return KeyboardButton::alt(); - - default: - int key = MapVirtualKey(wparam, 2); - if (isascii(key) && key != 0) { - if (GetKeyState(VK_SHIFT) >= 0) - key = tolower(key); - else { - switch (key) { - case '1': key = '!'; break; - case '2': key = '@'; break; - case '3': key = '#'; break; - case '4': key = '$'; break; - case '5': key = '%'; break; - case '6': key = '^'; break; - case '7': key = '&'; break; - case '8': key = '*'; break; - case '9': key = '('; break; - case '0': key = ')'; break; - case '-': key = '_'; break; - case '=': key = '+'; break; - case ',': key = '<'; break; - case '.': key = '>'; break; - case '/': key = '?'; break; - case ';': key = ':'; break; - case '\'': key = '"'; break; - case '[': key = '{'; break; - case ']': key = '}'; break; - case '\\': key = '|'; break; - case '`': key = '~'; break; - } - } - return KeyboardButton::ascii_key((uchar)key); - } - break; - } - return ButtonHandle::none(); -} diff --git a/panda/src/wgldisplay/wglGraphicsPipe.h b/panda/src/wgldisplay/wglGraphicsPipe.h index 3216edc81f..7ed272c7ce 100644 --- a/panda/src/wgldisplay/wglGraphicsPipe.h +++ b/panda/src/wgldisplay/wglGraphicsPipe.h @@ -30,11 +30,6 @@ #include #undef WINDOWS_LEAN_AND_MEAN -//////////////////////////////////////////////////////////////////// -// Defines -//////////////////////////////////////////////////////////////////// -class Xclass; - //////////////////////////////////////////////////////////////////// // Class : wglGraphicsPipe // Description : @@ -43,9 +38,6 @@ class EXPCL_PANDAGL wglGraphicsPipe : public InteractiveGraphicsPipe { public: wglGraphicsPipe(const PipeSpecifier&); - wglGraphicsWindow* find_window(HWND win); - ButtonHandle lookup_key(WPARAM wparam) const; - virtual TypeHandle get_window_type() const; public: @@ -61,19 +53,11 @@ private: static TypeHandle _type_handle; - int _width; - int _height; - bool _shift; - protected: wglGraphicsPipe(void); wglGraphicsPipe(const wglGraphicsPipe&); wglGraphicsPipe& operator=(const wglGraphicsPipe&); - - static LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, - LPARAM lparam); - LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); }; #endif diff --git a/panda/src/wgldisplay/wglGraphicsWindow.cxx b/panda/src/wgldisplay/wglGraphicsWindow.cxx index accf9c95e4..43ed0e2ef9 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.cxx +++ b/panda/src/wgldisplay/wglGraphicsWindow.cxx @@ -21,21 +21,525 @@ #include "config_wgldisplay.h" #include #include +#include #include #include #include #include #include +#include +#include +#include + +#define WGL_WGLEXT_PROTOTYPES +#include "wglext.h" //////////////////////////////////////////////////////////////////// // Static variables //////////////////////////////////////////////////////////////////// TypeHandle wglGraphicsWindow::_type_handle; +#define WGLWIN_CONFIGURE 0x4 + #define MOUSE_ENTERED 0 #define MOUSE_EXITED 1 -#define FONT_BITMAP_OGLDISPLAYLISTNUM 1000 // some arbitrary # +#define FONT_BITMAP_OGLDISPLAYLISTNUM 1000 // an arbitrary ID # + +#define LAST_ERROR 0 +#define ERRORBOX_TITLE "Panda3D Error" +#define WGL_WINDOWCLASSNAME "wglDisplay" + +typedef map HWND_PANDAWIN_MAP; + +HWND_PANDAWIN_MAP hwnd_pandawin_map; +wglGraphicsWindow *global_wglwinptr=NULL; // need this for temporary windproc + +typedef enum {Software, MCD, ICD} OGLDriverType; + +LONG WINAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam,LPARAM lparam); + +void PrintErrorMessage(DWORD msgID) { + LPTSTR pMessageBuffer; + + if(msgID==LAST_ERROR) + msgID=GetLastError(); + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL,msgID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language + (LPTSTR) &pMessageBuffer, // the weird ptrptr->ptr cast is intentional, see FORMAT_MESSAGE_ALLOCATE_BUFFER + 1024, NULL); + MessageBox(GetDesktopWindow(),pMessageBuffer,_T(ERRORBOX_TITLE),MB_OK); + wgldisplay_cat.fatal() << "System error msg: " << pMessageBuffer << endl; + LocalFree( pMessageBuffer ); +} + +// fn exists so AtExitFn can call it without refcntr blowing up since its !=0 +void wglGraphicsWindow::DestroyMe(bool bAtExit) { + + _exiting_window = true; // needed before DestroyWindow call + + if(_visual!=NULL) + free(_visual); + + // several GL drivers (voodoo,ATI, not nvidia) crash if we call these wgl deletion routines from + // an atexit() fn. So we just wont call them for now. We're exiting the app anyway. + if(!bAtExit) { + + if(gl_show_fps_meter) + glDeleteLists(FONT_BITMAP_OGLDISPLAYLISTNUM, 128); + + HGLRC curcxt=wglGetCurrentContext(); + if(curcxt!=NULL) + unmake_current(); + + if(_context!=NULL) + wglDeleteContext(_context); + } + + if(_hdc!=NULL) + ReleaseDC(_mwindow,_hdc); + + if(_mwindow!=NULL) { + DestroyWindow(_mwindow); + hwnd_pandawin_map.erase(_mwindow); + } + + if(_pCurrent_display_settings!=NULL) + delete _pCurrent_display_settings; + + if (_props._fullscreen) { + // revert to default display mode + ChangeDisplaySettings(NULL,0x0); + } + + global_wglwinptr=NULL; //should be safe to do this now, since anyone who needs it at CreateWin will just set it during creation +} + +//////////////////////////////////////////////////////////////////// +// Function: Destructor +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +wglGraphicsWindow::~wglGraphicsWindow(void) { + DestroyMe(false); +} + +void DestroyAllWindows(bool bAtExit) { + // need to go through all windows in map var and delete them + while(!hwnd_pandawin_map.empty()) { + // cant use a for loop cause DestroyMe erases things out from under us, so iterator is invalid + HWND_PANDAWIN_MAP::iterator pwin = hwnd_pandawin_map.begin(); + if((*pwin).second != NULL) + (*pwin).second->DestroyMe(bAtExit); + } +} + +void AtExitFn() { +#ifdef _DEBUG + wgldisplay_cat.spam() << "AtExitFn called\n"; +#endif + + DestroyAllWindows(true); +} + +// spare me the trouble of linking with dxguid.lib or defining ALL the dx guids in this .obj by #defining INITGUID +#define MY_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + EXTERN_C const GUID DECLSPEC_SELECTANY name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +MY_DEFINE_GUID( IID_IDirectDraw2, 0xB3A6F3E0,0x2B43,0x11CF,0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 ); + +//////////////////////////////////////////////////////////////////// +// Function: GetAvailVidMem +// Description: Uses DDraw to get available video memory +//////////////////////////////////////////////////////////////////// +static DWORD GetAvailVidMem(void) { + + LPDIRECTDRAW2 pDD2; + LPDIRECTDRAW pDD; + HRESULT hr; + + typedef HRESULT (WINAPI *DIRECTDRAWCREATEPROC)(GUID FAR *lpGUID,LPDIRECTDRAW FAR *lplpDD,IUnknown FAR *pUnkOuter); + DIRECTDRAWCREATEPROC pfnDDCreate=NULL; + + HINSTANCE DDHinst = LoadLibrary( "ddraw.dll" ); + if(DDHinst == 0) { + wgldisplay_cat.fatal() << "LoadLibrary() can't find DDRAW.DLL!" << endl; + exit(1); + } + + pfnDDCreate = (DIRECTDRAWCREATEPROC) GetProcAddress( DDHinst, "DirectDrawCreate" ); + + // just use DX5 DD interface, since that's the minimum ver we need + if(NULL == pfnDDCreate) { + wgldisplay_cat.fatal() << "GetProcAddress failed on DirectDrawCreate\n"; + exit(1); + } + + // Create the Direct Draw Object + hr = (*pfnDDCreate)((GUID *)DDCREATE_HARDWAREONLY, &pDD, NULL); + if(hr != DD_OK) { + wgldisplay_cat.fatal() + << "DirectDrawCreate failed : result = " << (void*)hr << endl; + exit(1); + } + + FreeLibrary(DDHinst); //undo LoadLib above, decrement ddrawl.dll refcnt (after DDrawCreate, since dont want to unload/reload) + + // need DDraw2 interface for GetAvailVidMem + hr = pDD->QueryInterface(IID_IDirectDraw2, (LPVOID *)&pDD2); + if(hr != DD_OK) { + wgldisplay_cat.fatal() << "DDraw QueryInterface failed : result = " << (void*)hr << endl; + exit(1); + } + + pDD->Release(); + + // Now we try to figure out if we can use requested screen resolution and best + // rendertarget bpp and still have at least 2 meg of texture vidmem + + // Get Current VidMem avail. Note this is only an estimate, when we switch to fullscreen + // mode from desktop, more vidmem will be available (typically 1.2 meg). I dont want + // to switch to fullscreen more than once due to the annoying monitor flicker, so try + // to figure out optimal mode using this estimate + DDSCAPS ddsCaps; + DWORD dwTotal,dwFree; + ZeroMemory(&ddsCaps,sizeof(DDSCAPS2)); + ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY; //set internally by DX anyway, dont think this any different than 0x0 + + if(FAILED( hr = pDD2->GetAvailableVidMem(&ddsCaps,&dwTotal,&dwFree))) { + wgldisplay_cat.fatal() << "GetAvailableVidMem failed : result = " << (void*)hr << endl; + exit(1); + } + +#ifdef _DEBUG + wgldisplay_cat.debug() << "before FullScreen switch: GetAvailableVidMem returns Total: " << dwTotal/1000000.0 << " Free: " << dwFree/1000000.0 << endl; +#endif + + pDD2->Release(); // bye-bye ddraw + + return dwFree; +} + +//////////////////////////////////////////////////////////////////// +// Function: config +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +void wglGraphicsWindow::config(void) { + + GraphicsWindow::config(); + + HINSTANCE hinstance = GetModuleHandle(NULL); + HWND hDesktopWindow = GetDesktopWindow(); + + global_wglwinptr = this; // need this until we get an HWND from CreateWindow + + _change_mask = 0; + _exiting_window = false; + _mouse_input_enabled = false; + _mouse_motion_enabled = false; + _mouse_passive_motion_enabled = false; + _mouse_entry_enabled = false; + _entry_state = -1; + _visual = NULL; + _context = NULL; + _hdc = NULL; + _window_inactive = false; + _pCurrent_display_settings = NULL; + + _mwindow = NULL; + _gsg = NULL; + +#if 0 +// bugbug need to add wdx handling routines + _WindowAdjustingType = NotAdjusting; + _hMouseCursor = NULL; + _bSizeIsMaximized=FALSE; +#endif + +#if 0 + // for gl, do this after window creation + // Create a GSG to manage the graphics + make_gsg(); + if(_gsg==NULL) { + wdxdisplay_cat.error() << "DXGSG creation failed!\n"; + exit(1); + } + _dxgsg = DCAST(DXGraphicsStateGuardian, _gsg); +#endif + + WNDCLASS wc; + + // Clear before filling in window structure! + ZeroMemory(&wc, sizeof(WNDCLASS)); + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) static_window_proc; + wc.hInstance = hinstance; + + string windows_icon_filename = get_icon_filename_().to_os_specific(); + + if(!windows_icon_filename.empty()) { + // Note: LoadImage seems to cause win2k internal heap corruption (outputdbgstr warnings) + // if icon is more than 8bpp + wc.hIcon = (HICON) LoadImage(NULL, windows_icon_filename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE); + } else { + wc.hIcon = NULL; // use default app icon + } + + wc.hCursor = _hMouseCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = WGL_WINDOWCLASSNAME; + + if(!RegisterClass(&wc)) { + wgldisplay_cat.fatal() << "could not register window class!" << endl; + exit(1); + } + + // rect now contains the coords for the entire window, not the client + if (_props._fullscreen) { + DWORD dwWidth = _props._xsize; + DWORD dwHeight = _props._ysize; + + HDC scrnDC=GetDC(hDesktopWindow); + DWORD drvr_ver=GetDeviceCaps(scrnDC,DRIVERVERSION); + DWORD cur_bitdepth=GetDeviceCaps(scrnDC,BITSPIXEL); + DWORD cur_scrnwidth=GetDeviceCaps(scrnDC,HORZRES); + DWORD cur_scrnheight=GetDeviceCaps(scrnDC,VERTRES); + ReleaseDC(hDesktopWindow,scrnDC); + + DWORD dwFullScreenBitDepth=cur_bitdepth; + + // dont pick any video modes < MIN_REFRESH_RATE Hz + #define MIN_REFRESH_RATE 60 + + // EnumDisplaySettings may indicate 0 or 1 for refresh rate, which means use driver default rate + #define ACCEPTABLE_REFRESH_RATE(RATE) ((RATE >= MIN_REFRESH_RATE) || (RATE==0) || (RATE==1)) + + #define LOWVIDMEMTHRESHOLD 3500000 + if(GetAvailVidMem() < LOWVIDMEMTHRESHOLD) { + wgldisplay_cat.debug() << "small video memory card detect, switching fullscreen to minimum 640x480x16 config\n"; + // we're going to need 640x480 at 16 bit to save enough tex vidmem + dwFullScreenBitDepth=16; + dwWidth=640; + dwHeight=480; + } + + DEVMODE dm; + bool bGoodModeFound=false; + BOOL bGotNewMode; + int j=0; + + while(1) { + memset( &dm, 0, sizeof( dm ) ); + dm.dmSize = sizeof( dm ); + + bGotNewMode=EnumDisplaySettings(NULL,j,&dm); + if(!bGotNewMode) + break; + + if((dm.dmPelsWidth==dwWidth) && (dm.dmPelsHeight==dwHeight) && + (dm.dmBitsPerPel==dwFullScreenBitDepth) && + ACCEPTABLE_REFRESH_RATE(dm.dmDisplayFrequency)) { + bGoodModeFound=true; + break; + } + j++; + } + + if(!bGoodModeFound) { + wgldisplay_cat.fatal() << "Videocard has no supported display resolutions at specified res ( " << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<" )\n"; + exit(1); + } + + DWORD style = WS_POPUP | WS_MAXIMIZE; + + // I'd prefer to CreateWindow after DisplayChange in case it messes up GL somehow, + // but I need the window's black background to cover up the desktop during the mode change + _mwindow = CreateWindow(WGL_WINDOWCLASSNAME, _props._title.c_str(), + style,0,0,dwWidth,dwHeight,hDesktopWindow, NULL, hinstance, 0); + + // move window to top of zorder, + SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); + + ShowWindow(_mwindow, SW_SHOWNORMAL); + ShowWindow(_mwindow, SW_SHOWNORMAL); + + int chg_result = ChangeDisplaySettings(&dm, CDS_FULLSCREEN); + + if(chg_result!=DISP_CHANGE_SUCCESSFUL) { + wgldisplay_cat.fatal() << "ChangeDisplaySettings failed (error code: " << chg_result <<") for specified res ( " << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<" ), " << dm.dmDisplayFrequency << "Hz\n"; + exit(1); + } + + _pCurrent_display_settings = new(DEVMODE); + memcpy(_pCurrent_display_settings,&dm,sizeof(DEVMODE)); + + _props._xorg = 0; + _props._yorg = 0; + _props._xsize = dwWidth; + _props._ysize = dwHeight; + + if(wgldisplay_cat.is_debug()) + wgldisplay_cat.debug() << "set fullscreen mode at res ( " << dwWidth << " X " << dwHeight << " X " << dwFullScreenBitDepth <<" ), " << dm.dmDisplayFrequency << "Hz\n"; + } else { + + DWORD style; + RECT win_rect; + SetRect(&win_rect, _props._xorg, _props._yorg, _props._xorg + _props._xsize, + _props._yorg + _props._ysize); + + style = WS_POPUP | WS_MAXIMIZE; + + if(_props._border) { + style |= WS_OVERLAPPEDWINDOW; + } + + BOOL bRes = AdjustWindowRect(&win_rect, style, FALSE); //compute window size based on desired client area size + + if(!bRes) { + wgldisplay_cat.fatal() << "AdjustWindowRect failed!" << endl; + exit(1); + } + + // make sure origin is on screen, slide far bounds over if necessary + if(win_rect.left < 0) { + win_rect.right += abs(win_rect.left); win_rect.left = 0; + } + if(win_rect.top < 0) { + win_rect.bottom += abs(win_rect.top); win_rect.top = 0; + } + + _mwindow = CreateWindow(WGL_WINDOWCLASSNAME, _props._title.c_str(), + style, win_rect.left, win_rect.top, win_rect.right-win_rect.left, + win_rect.bottom-win_rect.top, + NULL, NULL, hinstance, 0); + } + + if(!_mwindow) { + wgldisplay_cat.fatal() << "CreateWindow() failed!" << endl; + PrintErrorMessage(LAST_ERROR); + exit(1); + } + + hwnd_pandawin_map[_mwindow] = this; + + // move window to top of zorder + SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); + + _hdc = GetDC(_mwindow); + + // Configure the framebuffer according to parameters specified in _props + // Initializes _visual + int pfnum=choose_visual(); + + // int pfnum=ChoosePixelFormat(_hdc, _visual); + if(wgldisplay_cat.is_debug()) + wgldisplay_cat.debug() << "wglGraphicsWindow::config() - picking pixfmt #"<< pfnum <dwFlags & (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW)) { - if (visual->iPixelType == PFD_TYPE_COLORINDEX && - visual->cColorBits >= 24) { - *value = 0; - } else { - *value = 1; - } - } else { - *value = 0; - } - break; - case GLX_BUFFER_SIZE: - if (visual->iPixelType == PFD_TYPE_RGBA) - *value = visual->cColorBits; - else - *value = 8; - break; - case GLX_LEVEL: - *value = visual->bReserved; - break; - case GLX_RGBA: - *value = visual->iPixelType == PFD_TYPE_RGBA; - break; - case GLX_DOUBLEBUFFER: - *value = visual->dwFlags & PFD_DOUBLEBUFFER; - break; - case GLX_STEREO: - *value = visual->dwFlags & PFD_STEREO; - break; - case GLX_AUX_BUFFERS: - *value = visual->cAuxBuffers; - break; - case GLX_RED_SIZE: - *value = visual->cRedBits; - break; - case GLX_GREEN_SIZE: - *value = visual->cGreenBits; - break; - case GLX_BLUE_SIZE: - *value = visual->cBlueBits; - break; - case GLX_ALPHA_SIZE: - *value = visual->cAlphaBits; - break; - case GLX_DEPTH_SIZE: - *value = visual->cDepthBits; - break; - case GLX_STENCIL_SIZE: - *value = visual->cStencilBits; - break; - case GLX_ACCUM_RED_SIZE: - *value = visual->cAccumRedBits; - break; - case GLX_ACCUM_GREEN_SIZE: - *value = visual->cAccumGreenBits; - break; - case GLX_ACCUM_BLUE_SIZE: - *value = visual->cAccumBlueBits; - break; - case GLX_ACCUM_ALPHA_SIZE: - *value = visual->cAccumAlphaBits; - break; - } -} - -#if 0 -//////////////////////////////////////////////////////////////////// -// Function: choose visual -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -int wglGraphicsWindow::choose_visual(void) { - wglGraphicsPipe* pipe = DCAST(wglGraphicsPipe, _pipe); - - int mask = _props._mask; - - wgldisplay_cat.info() - << "wglGraphicsWindow::mask =0x" << (void*) _props._mask - << endl; - - int want_depth_bits = _props._want_depth_bits; - int want_color_bits = _props._want_color_bits; - - if (mask & W_MULTISAMPLE) { - wgldisplay_cat.info() - << "wglGraphicsWindow::config() - multisample not supported" - << endl; - mask &= ~W_MULTISAMPLE; - } - - _visual = try_for_visual(pipe, mask, want_depth_bits, want_color_bits); - - // This is the severity level at which we'll report the details of - // the visual we actually do find. Normally, it's debug-level - // information: we don't care about that much detail. - NotifySeverity show_visual_severity = NS_debug; - - if (_visual == NULL) { - wgldisplay_cat.info() - << "wglGraphicsWindow::choose_visual() - visual with requested\n" - << " capabilities not found; trying for lesser visual.\n"; - - // If we're unable to get the visual we asked for, however, we - // probably *do* care to know the details about what we actually - // got, even if we don't have debug mode set. So we'll report the - // visual at a higher level. - show_visual_severity = NS_info; - - bool special_size_request = - (want_depth_bits != 1 || want_color_bits != 1); - - // We try to be smart about choosing a close match for the visual. - // First, we'll eliminate some of the more esoteric options one at - // a time, then two at a time, and finally we'll try just the bare - // minimum. - - if (special_size_request) { - // Actually, first we'll eliminate all of the minimum sizes, to - // try to open a window with all of the requested options, but - // maybe not as many bits in some options as we'd like. - _visual = try_for_visual(pipe, mask); - } - - if (_visual == NULL) { - // Ok, not good enough. Now try to eliminate options, but keep - // as many bits as we asked for. - - // This array keeps the bitmasks of options that we pull out of - // the requested mask, in order. - - static const int strip_properties[] = { - // One esoteric option removed. - W_MULTISAMPLE, - W_STENCIL, - W_ACCUM, - W_ALPHA, - W_STEREO, - - // Two esoteric options removed. - W_STENCIL | W_MULTISAMPLE, - W_ACCUM | W_MULTISAMPLE, - W_ALPHA | W_MULTISAMPLE, - W_STEREO | W_MULTISAMPLE, - W_STENCIL | W_ACCUM, - W_ALPHA | W_STEREO, - W_STENCIL | W_ACCUM | W_MULTISAMPLE, - W_ALPHA | W_STEREO | W_MULTISAMPLE, - - // All esoteric options removed. - W_STENCIL | W_ACCUM | W_ALPHA | W_STEREO | W_MULTISAMPLE, - - // All esoteric options, plus some we'd really really prefer, - // removed. - W_STENCIL | W_ACCUM | W_ALPHA | W_STEREO | W_MULTISAMPLE | W_DOUBLE, - - // A zero marks the end of the array. - 0 - }; - - pset tried_masks; - tried_masks.insert(mask); - - int i; - for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) { - int new_mask = mask & ~strip_properties[i]; - if (tried_masks.insert(new_mask).second) { - _visual = try_for_visual(pipe, new_mask, want_depth_bits, - want_color_bits); - } - } - - if (special_size_request) { - tried_masks.clear(); - tried_masks.insert(mask); - - if (_visual == NULL) { - // Try once more, this time eliminating all of the size - // requests. - for (i = 0; _visual == NULL && strip_properties[i] != 0; i++) { - int new_mask = mask & ~strip_properties[i]; - if (tried_masks.insert(new_mask).second) { - _visual = try_for_visual(pipe, new_mask); - } - } - } - } - - if (_visual == NULL) { - // Here's our last-ditch desparation attempt: give us any GLX - // visual at all! - _visual = try_for_visual(pipe, 0); - } - - if (_visual == NULL) { - wgldisplay_cat.fatal() - << "wglGraphicsWindow::choose_visual() - could not get any " - "visual." << endl; - exit(1); - } - } - } - - if (wgldisplay_cat.is_on(show_visual_severity)) { - int render_mode, double_buffer, stereo, red_size, green_size, blue_size, - alpha_size, ared_size, agreen_size, ablue_size, aalpha_size, - depth_size, stencil_size; - - get_config(_visual, GLX_RGBA, &render_mode); - get_config(_visual, GLX_DOUBLEBUFFER, &double_buffer); - get_config(_visual, GLX_STEREO, &stereo); - get_config(_visual, GLX_RED_SIZE, &red_size); - get_config(_visual, GLX_GREEN_SIZE, &green_size); - get_config(_visual, GLX_BLUE_SIZE, &blue_size); - get_config(_visual, GLX_ALPHA_SIZE, &alpha_size); - get_config(_visual, GLX_ACCUM_RED_SIZE, &ared_size); - get_config(_visual, GLX_ACCUM_GREEN_SIZE, &agreen_size); - get_config(_visual, GLX_ACCUM_BLUE_SIZE, &ablue_size); - get_config(_visual, GLX_ACCUM_ALPHA_SIZE, &aalpha_size); - get_config(_visual, GLX_DEPTH_SIZE, &depth_size); - get_config(_visual, GLX_STENCIL_SIZE, &stencil_size); - - wgldisplay_cat.out(show_visual_severity) - << "GLX Visual Info (# bits of each):" << endl - << " RGBA: " << red_size << " " << green_size << " " << blue_size - << " " << alpha_size << endl - << " Accum RGBA: " << ared_size << " " << agreen_size << " " - << ablue_size << " " << aalpha_size << endl - << " Depth: " << depth_size << endl - << " Stencil: " << stencil_size << endl - << " DoubleBuffer? " << double_buffer << endl - << " Stereo? " << stereo << endl; - } -} -#else - -typedef enum {Software, MCD, ICD} OGLDriverType; #ifdef _DEBUG void PrintPFD(PIXELFORMATDESCRIPTOR *pfd,char *msg) { @@ -511,7 +747,6 @@ void PrintPFD(PIXELFORMATDESCRIPTOR *pfd,char *msg) { // Description: //////////////////////////////////////////////////////////////////// int wglGraphicsWindow::choose_visual(void) { - wglGraphicsPipe* pipe = DCAST(wglGraphicsPipe, _pipe); int mask = _props._mask; int want_depth_bits = _props._want_depth_bits; @@ -544,8 +779,6 @@ int wglGraphicsWindow::choose_visual(void) { for(i=1;i<=MaxPixFmtNum;i++) { DescribePixelFormat(_hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd); - if (wgldisplay_cat.is_debug()) - wgldisplay_cat->debug() << "----------------" << endl; if((pfd.dwFlags & PFD_GENERIC_ACCELERATED) && (pfd.dwFlags & PFD_GENERIC_FORMAT)) drvtype=MCD; @@ -553,11 +786,12 @@ int wglGraphicsWindow::choose_visual(void) { drvtype=ICD; else { drvtype=Software; - if (wgldisplay_cat.is_debug()) - wgldisplay_cat->debug() << "skipping software driver" << endl; continue; // skipping all SW fmts } + if(wgldisplay_cat.is_debug()) + wgldisplay_cat->debug() << "----------------" << endl; + if((pfd.iPixelType == PFD_TYPE_COLORINDEX) && !(mask & W_INDEX)) continue; @@ -571,21 +805,21 @@ int wglGraphicsWindow::choose_visual(void) { DWORD dwReqFlags=(PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW); if (wgldisplay_cat.is_debug()) { - if (mask & W_ALPHA) - wgldisplay_cat->debug() << "want alpha, pfd says '" - << (int)(pfd.cAlphaBits) << "'" << endl; - if (mask & W_DEPTH) - wgldisplay_cat->debug() << "want depth, pfd says '" - << (int)(pfd.cDepthBits) << "'" << endl; - if (mask & W_STENCIL) - wgldisplay_cat->debug() << "want stencil, pfd says '" - << (int)(pfd.cStencilBits) << "'" << endl; - wgldisplay_cat->debug() << "final flag check " - << (int)(pfd.dwFlags & dwReqFlags) << " =? " - << (int)dwReqFlags << endl; - wgldisplay_cat->debug() << "pfd bits = " << (int)(pfd.cColorBits) - << endl; - wgldisplay_cat->debug() << "cur_bpp = " << cur_bpp << endl; + if (mask & W_ALPHA) + wgldisplay_cat->debug() << "want alpha, pfd says '" + << (int)(pfd.cAlphaBits) << "'" << endl; + if (mask & W_DEPTH) + wgldisplay_cat->debug() << "want depth, pfd says '" + << (int)(pfd.cDepthBits) << "'" << endl; + if (mask & W_STENCIL) + wgldisplay_cat->debug() << "want stencil, pfd says '" + << (int)(pfd.cStencilBits) << "'" << endl; + wgldisplay_cat->debug() << "final flag check " + << (int)(pfd.dwFlags & dwReqFlags) << " =? " + << (int)dwReqFlags << endl; + wgldisplay_cat->debug() << "pfd bits = " << (int)(pfd.cColorBits) + << endl; + wgldisplay_cat->debug() << "cur_bpp = " << cur_bpp << endl; } if(mask & W_DOUBLE) @@ -636,8 +870,7 @@ int wglGraphicsWindow::choose_visual(void) { return i; } -#endif - +#if 0 //////////////////////////////////////////////////////////////////// // Function: adjust_coords // Access: @@ -672,151 +905,13 @@ adjust_coords(int &xorg, int &yorg, int &xsize, int &ysize) { xsize = rect.right - rect.left; ysize = rect.bottom - rect.top; } - -//////////////////////////////////////////////////////////////////// -// Function: config -// Access: -// Description: -//////////////////////////////////////////////////////////////////// -void wglGraphicsWindow::config(void) { - GraphicsWindow::config(); - - wglGraphicsPipe* pipe = DCAST(wglGraphicsPipe, _pipe); - HINSTANCE hinstance = GetModuleHandle(NULL); - HWND desktop = GetDesktopWindow(); - - if (_props._fullscreen) { - // Note: to set fullscreen, use 'fullscreen #t' in Configurc - // This just runs fullscrn at current display res & depth - // want to be smarter about this like wdxdisplay and pick a res - // that will have HW acceleration and adequate texmem, but we cant - // get the appropriate info yet in GL (unlike DX). - - // BUGBUG: The Configrc res vars (_props.x/ysize) are ignored; - // instead we should consider switching to the specified res - // (cant use DDraw for this though due to inconsistent driver support) - - _props._xorg = 0; - _props._yorg = 0; - _props._xsize = GetSystemMetrics(SM_CXSCREEN); - _props._ysize = GetSystemMetrics(SM_CYSCREEN); - _mwindow = CreateWindow("wglFullscreen", _props._title.c_str(), - WS_POPUP | WS_MAXIMIZE, - _props._xorg, _props._yorg, _props._xsize, _props._ysize, - desktop, NULL, hinstance, 0); - - } else { - - int xorg = _props._xorg; - int yorg = _props._yorg; - int xsize = _props._xsize; - int ysize = _props._ysize; - - int style = WS_POPUP | WS_MAXIMIZE; - if (_props._border == true) { - style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW; - adjust_coords(xorg, yorg, xsize, ysize); - } - - _mwindow = CreateWindow("wglStandard", _props._title.c_str(), - style, xorg, yorg, xsize, ysize, - desktop, NULL, hinstance, 0); - } - - if (!_mwindow) { - wgldisplay_cat.fatal() - << "wglGraphicsWindow::config() - failed to create Mwindow" << endl; - exit(1); - } - - _hdc = GetDC(_mwindow); - - // Configure the framebuffer according to parameters specified in _props - // Initializes _visual - int pfnum=choose_visual(); - -// int pfnum=ChoosePixelFormat(_hdc, _visual); - wgldisplay_cat.debug() - << "wglGraphicsWindow::config() - picking pixfmt #"<< pfnum <window_proc(hwnd, msg, wparam, lparam); + } else if(global_wglwinptr!=NULL){ + // this stuff should only be used during CreateWindow() + return global_wglwinptr->window_proc(hwnd, msg, wparam, lparam); + } else { + // should never need this?? (maybe at shutdwn?) + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: window_proc +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +LONG WINAPI wglGraphicsWindow:: +window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + int button = -1; + int x, y, width, height; + + switch (msg) { + case WM_CREATE: + break; + + case WM_CLOSE: + PostQuitMessage(0); // send WM_QUIT message + return 0; + + case WM_ACTIVATE: { + if (_props._fullscreen && (!_exiting_window)) { + // handle switching out of fullscreen mode differently than windowed mode. + // here we want to suspend all gfx and execution, switch display modes and minimize ourself + // until we are switched back to + + if(wparam==WA_INACTIVE) { + if(wgldisplay_cat.is_spam()) + wgldisplay_cat.spam() << "WGL window deactivated, releasing gl context and waiting...\n"; + _window_inactive = true; + unmake_current(); + + // bugbug: this isnt working right now on many drivers. may have to + // destroy window and recreate a new OGL context for this to work +#ifdef ENABLE_ALTTAB_DISPLAYCHANGE + // revert to default display mode + ChangeDisplaySettings(NULL,0x0); +#endif + ShowWindow(_mwindow, SW_MINIMIZE); + } else { + if(_window_inactive) { + if(wgldisplay_cat.is_spam()) + wgldisplay_cat.spam() << "WGL window re-activated...\n"; + _window_inactive = false; + + // move window to top of zorder, + SetWindowPos(_mwindow, HWND_TOP, 0,0,0,0, SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOSIZE); + ShowWindow(_mwindow, SW_SHOWNORMAL); + +#ifdef ENABLE_ALTTAB_DISPLAYCHANGE + ChangeDisplaySettings(_pCurrent_display_settings,CDS_FULLSCREEN); +#endif + + make_current(); + } + } + return 0; + } else break; + } + + case WM_PAINT: { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + return 0; + } + + case WM_SYSCHAR: + case WM_CHAR: + return 0; + + case WM_SYSKEYDOWN: + case WM_KEYDOWN: { + POINT point; + make_current(); + GetCursorPos(&point); + ScreenToClient(hwnd, &point); + handle_keypress(lookup_key(wparam), point.x, point.y); + } + + case WM_SYSKEYUP: + case WM_KEYUP: { + // dont need x,y for this + handle_keyrelease(lookup_key(wparam)); + return 0; + } + case WM_LBUTTONDOWN: + button = 0; + case WM_MBUTTONDOWN: + if (button < 0) + button = 1; + case WM_RBUTTONDOWN: + if (button < 0) + button = 2; + SetCapture(hwnd); + // Win32 doesn't return the same numbers as X does when the mouse + // goes beyond the upper or left side of the window + x = LOWORD(lparam); + y = HIWORD(lparam); + if (x & 1 << 15) + x -= (1 << 16); + if (y & 1 << 15) + y -= (1 << 16); + // make_current(); what does OGL have to do with mouse input?? + handle_keypress(MouseButton::button(button), x, y); + return 0; + case WM_LBUTTONUP: + button = 0; + case WM_MBUTTONUP: + if (button < 0) + button = 1; + case WM_RBUTTONUP: + if (button < 0) + button = 2; + ReleaseCapture(); + #if 0 + x = LOWORD(lparam); + y = HIWORD(lparam); + if (x & 1 << 15) + x -= (1 << 16); + if (y & 1 << 15) + y -= (1 << 16); + // make_current(); what does OGL have to do with mouse input?? + #endif + handle_keyrelease(MouseButton::button(button)); + return 0; + + case WM_MOUSEMOVE: + x = LOWORD(lparam); + y = HIWORD(lparam); + if (x & 1 << 15) + x -= (1 << 16); + if (y & 1 << 15) + y -= (1 << 16); + if (mouse_motion_enabled() && + (wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) { + // make_current(); what does OGL have to do with mouse input?? + handle_mouse_motion(x, y); + } else if (mouse_passive_motion_enabled() && + ((wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)) { + // make_current(); what does OGL have to do with mouse input?? + handle_mouse_motion(x, y); + } + return 0; + + case WM_SIZE: + width = LOWORD(lparam); + height = HIWORD(lparam); + handle_reshape(width, height); + return 0; + + case WM_SETFOCUS: + SetCursor(_hMouseCursor); + if (mouse_entry_enabled()) { + make_current(); + handle_mouse_entry(MOUSE_ENTERED); + } + return 0; + + case WM_KILLFOCUS: + if (mouse_entry_enabled()) { + //make_current(); this doesnt make any sense, we're leaving our window + handle_mouse_entry(MOUSE_EXITED); + } + return 0; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +//////////////////////////////////////////////////////////////////// +// Function: lookup_key +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +ButtonHandle +wglGraphicsWindow::lookup_key(WPARAM wparam) const { + // probably would be faster with a map var + switch (wparam) { + case VK_BACK: return KeyboardButton::backspace(); + case VK_TAB: return KeyboardButton::tab(); + case VK_ESCAPE: return KeyboardButton::escape(); + case VK_SPACE: return KeyboardButton::space(); + case VK_UP: return KeyboardButton::up(); + case VK_DOWN: return KeyboardButton::down(); + case VK_LEFT: return KeyboardButton::left(); + case VK_RIGHT: return KeyboardButton::right(); + case VK_PRIOR: return KeyboardButton::page_up(); + case VK_NEXT: return KeyboardButton::page_down(); + case VK_HOME: return KeyboardButton::home(); + case VK_END: return KeyboardButton::end(); + case VK_F1: return KeyboardButton::f1(); + case VK_F2: return KeyboardButton::f2(); + case VK_F3: return KeyboardButton::f3(); + case VK_F4: return KeyboardButton::f4(); + case VK_F5: return KeyboardButton::f5(); + case VK_F6: return KeyboardButton::f6(); + case VK_F7: return KeyboardButton::f7(); + case VK_F8: return KeyboardButton::f8(); + case VK_F9: return KeyboardButton::f9(); + case VK_F10: return KeyboardButton::f10(); + case VK_F11: return KeyboardButton::f11(); + case VK_F12: return KeyboardButton::f12(); + case VK_INSERT: return KeyboardButton::insert(); + case VK_DELETE: return KeyboardButton::del(); + + case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: + return KeyboardButton::shift(); + + case VK_CONTROL: + case VK_LCONTROL: + case VK_RCONTROL: + return KeyboardButton::control(); + + case VK_MENU: + case VK_LMENU: + case VK_RMENU: + return KeyboardButton::alt(); + + default: + int key = MapVirtualKey(wparam, 2); + if (isascii(key) && key != 0) { + if (GetKeyState(VK_SHIFT) >= 0) + key = tolower(key); + else { + switch (key) { + case '1': key = '!'; break; + case '2': key = '@'; break; + case '3': key = '#'; break; + case '4': key = '$'; break; + case '5': key = '%'; break; + case '6': key = '^'; break; + case '7': key = '&'; break; + case '8': key = '*'; break; + case '9': key = '('; break; + case '0': key = ')'; break; + case '-': key = '_'; break; + case '=': key = '+'; break; + case ',': key = '<'; break; + case '.': key = '>'; break; + case '/': key = '?'; break; + case ';': key = ':'; break; + case '\'': key = '"'; break; + case '[': key = '{'; break; + case ']': key = '}'; break; + case '\\': key = '|'; break; + case '`': key = '~'; break; + } + } + return KeyboardButton::ascii_key((uchar)key); + } + break; + } + return ButtonHandle::none(); +} + + +//////////////////////////////////////////////////////////////////// +// Function: get_config +// Access: +// Description: +//////////////////////////////////////////////////////////////////// +void wglGraphicsWindow:: +get_config(PIXELFORMATDESCRIPTOR *visual, int attrib, int *value) { + if (visual == NULL) + return; + + switch (attrib) { + case GLX_USE_GL: + if (visual->dwFlags & (PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW)) { + if (visual->iPixelType == PFD_TYPE_COLORINDEX && + visual->cColorBits >= 24) { + *value = 0; + } else { + *value = 1; + } + } else { + *value = 0; + } + break; + case GLX_BUFFER_SIZE: + if (visual->iPixelType == PFD_TYPE_RGBA) + *value = visual->cColorBits; + else + *value = 8; + break; + case GLX_LEVEL: + *value = visual->bReserved; + break; + case GLX_RGBA: + *value = visual->iPixelType == PFD_TYPE_RGBA; + break; + case GLX_DOUBLEBUFFER: + *value = visual->dwFlags & PFD_DOUBLEBUFFER; + break; + case GLX_STEREO: + *value = visual->dwFlags & PFD_STEREO; + break; + case GLX_AUX_BUFFERS: + *value = visual->cAuxBuffers; + break; + case GLX_RED_SIZE: + *value = visual->cRedBits; + break; + case GLX_GREEN_SIZE: + *value = visual->cGreenBits; + break; + case GLX_BLUE_SIZE: + *value = visual->cBlueBits; + break; + case GLX_ALPHA_SIZE: + *value = visual->cAlphaBits; + break; + case GLX_DEPTH_SIZE: + *value = visual->cDepthBits; + break; + case GLX_STENCIL_SIZE: + *value = visual->cStencilBits; + break; + case GLX_ACCUM_RED_SIZE: + *value = visual->cAccumRedBits; + break; + case GLX_ACCUM_GREEN_SIZE: + *value = visual->cAccumGreenBits; + break; + case GLX_ACCUM_BLUE_SIZE: + *value = visual->cAccumBlueBits; + break; + case GLX_ACCUM_ALPHA_SIZE: + *value = visual->cAccumAlphaBits; + break; + } +} + + diff --git a/panda/src/wgldisplay/wglGraphicsWindow.h b/panda/src/wgldisplay/wglGraphicsWindow.h index 6c34ba489f..eaa89d60a7 100644 --- a/panda/src/wgldisplay/wglGraphicsWindow.h +++ b/panda/src/wgldisplay/wglGraphicsWindow.h @@ -33,9 +33,6 @@ //////////////////////////////////////////////////////////////////// class wglGraphicsPipe; -const int WGLWIN_CONFIGURE = 4; -const int WGLWIN_EVENT = 8; - #define GLX_USE_GL 1 /* support GLX rendering */ #define GLX_BUFFER_SIZE 2 /* depth of the color buffer */ #define GLX_LEVEL 3 /* level in plane stacking */ @@ -86,11 +83,11 @@ public: void handle_mouse_motion( int x, int y ); void handle_mouse_entry( int state ); void handle_keypress( ButtonHandle key, int x, int y ); - void handle_keyrelease( ButtonHandle key, int x, int y ); + void handle_keyrelease( ButtonHandle key ); protected: PIXELFORMATDESCRIPTOR* try_for_visual(wglGraphicsPipe *pipe, - int mask, int want_depth_bits = 1, int want_color_bits = 1); + int mask, int want_depth_bits = 1, int want_color_bits = 1); int choose_visual(void); static void get_config(PIXELFORMATDESCRIPTOR* visual, int attrib, int *value); virtual void config( void ); @@ -103,9 +100,6 @@ protected: void handle_changes(void); void process_events(void); - void idle_wait(void); - - void adjust_coords(int &xorg, int &yorg, int &xsize, int &ysize); public: uint _change_mask; @@ -116,6 +110,12 @@ private: HDC _hdc; PIXELFORMATDESCRIPTOR* _visual; HPALETTE _colormap; + HCURSOR _hMouseCursor; + + DEVMODE *_pCurrent_display_settings; + + bool _window_inactive; + bool _exiting_window; bool _mouse_input_enabled; bool _mouse_motion_enabled; @@ -123,7 +123,7 @@ private: bool _mouse_entry_enabled; int _entry_state; bool _ignore_key_repeat; - int _full_height, _full_width; + int _full_height, _full_width; // vars for frames/sec meter DWORD _start_time; @@ -131,12 +131,18 @@ private: DWORD _cur_frame_count; float _current_fps; + string _extensions_str; + public: static TypeHandle get_class_type(void); static void init_type(void); virtual TypeHandle get_type(void) const; virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + ButtonHandle lookup_key(WPARAM wparam) const; + void DestroyMe(bool bAtExit); + private: static TypeHandle _type_handle; }; diff --git a/panda/src/wgldisplay/wglext.h b/panda/src/wgldisplay/wglext.h new file mode 100644 index 0000000000..f00f253219 --- /dev/null +++ b/panda/src/wgldisplay/wglext.h @@ -0,0 +1,401 @@ +#ifndef __wglext_h_ +#define __wglext_h_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** License Applicability. Except to the extent portions of this file are +** made subject to an alternative license as permitted in the SGI Free +** Software License B, Version 1.1 (the "License"), the contents of this +** file are subject only to the provisions of the License. You may not use +** this file except in compliance with the License. You may obtain a copy +** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 +** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: +** +** http://oss.sgi.com/projects/FreeB +** +** Note that, as provided in the License, the Software is distributed on an +** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS +** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND +** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A +** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. +** +** Original Code. The Original Code is: OpenGL Sample Implementation, +** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, +** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. +** Copyright in any portions created by third parties is as indicated +** elsewhere herein. All Rights Reserved. +** +** Additional Notice Provisions: This software was created using the +** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has +** not been independently verified as being compliant with the OpenGL(R) +** version 1.2.1 Specification. +*/ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif + +/*************************************************************/ + +/* Header file version number */ +#define WGL_WGLEXT_VERSION 1 + +#ifndef WGL_ARB_buffer_region +#define WGL_FRONT_COLOR_BUFFER_BIT_ARB 0x00000001 +#define WGL_BACK_COLOR_BUFFER_BIT_ARB 0x00000002 +#define WGL_DEPTH_BUFFER_BIT_ARB 0x00000004 +#define WGL_STENCIL_BUFFER_BIT_ARB 0x00000008 +#endif + +#ifndef WGL_ARB_extensions_string +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C +#endif + +#ifndef WGL_ARB_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_ARB 0x2043 +#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054 +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_DRAW_TO_PBUFFER_ARB 0x202D +#define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E +#define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030 +#define WGL_PBUFFER_LARGEST_ARB 0x2033 +#define WGL_PBUFFER_WIDTH_ARB 0x2034 +#define WGL_PBUFFER_HEIGHT_ARB 0x2035 +#define WGL_PBUFFER_LOST_ARB 0x2036 +#endif + +#ifndef WGL_EXT_make_current_read +#define ERROR_INVALID_PIXEL_TYPE_EXT 0x2043 +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_NUMBER_PIXEL_FORMATS_EXT 0x2000 +#define WGL_DRAW_TO_WINDOW_EXT 0x2001 +#define WGL_DRAW_TO_BITMAP_EXT 0x2002 +#define WGL_ACCELERATION_EXT 0x2003 +#define WGL_NEED_PALETTE_EXT 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_EXT 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_EXT 0x2006 +#define WGL_SWAP_METHOD_EXT 0x2007 +#define WGL_NUMBER_OVERLAYS_EXT 0x2008 +#define WGL_NUMBER_UNDERLAYS_EXT 0x2009 +#define WGL_TRANSPARENT_EXT 0x200A +#define WGL_TRANSPARENT_VALUE_EXT 0x200B +#define WGL_SHARE_DEPTH_EXT 0x200C +#define WGL_SHARE_STENCIL_EXT 0x200D +#define WGL_SHARE_ACCUM_EXT 0x200E +#define WGL_SUPPORT_GDI_EXT 0x200F +#define WGL_SUPPORT_OPENGL_EXT 0x2010 +#define WGL_DOUBLE_BUFFER_EXT 0x2011 +#define WGL_STEREO_EXT 0x2012 +#define WGL_PIXEL_TYPE_EXT 0x2013 +#define WGL_COLOR_BITS_EXT 0x2014 +#define WGL_RED_BITS_EXT 0x2015 +#define WGL_RED_SHIFT_EXT 0x2016 +#define WGL_GREEN_BITS_EXT 0x2017 +#define WGL_GREEN_SHIFT_EXT 0x2018 +#define WGL_BLUE_BITS_EXT 0x2019 +#define WGL_BLUE_SHIFT_EXT 0x201A +#define WGL_ALPHA_BITS_EXT 0x201B +#define WGL_ALPHA_SHIFT_EXT 0x201C +#define WGL_ACCUM_BITS_EXT 0x201D +#define WGL_ACCUM_RED_BITS_EXT 0x201E +#define WGL_ACCUM_GREEN_BITS_EXT 0x201F +#define WGL_ACCUM_BLUE_BITS_EXT 0x2020 +#define WGL_ACCUM_ALPHA_BITS_EXT 0x2021 +#define WGL_DEPTH_BITS_EXT 0x2022 +#define WGL_STENCIL_BITS_EXT 0x2023 +#define WGL_AUX_BUFFERS_EXT 0x2024 +#define WGL_NO_ACCELERATION_EXT 0x2025 +#define WGL_GENERIC_ACCELERATION_EXT 0x2026 +#define WGL_FULL_ACCELERATION_EXT 0x2027 +#define WGL_SWAP_EXCHANGE_EXT 0x2028 +#define WGL_SWAP_COPY_EXT 0x2029 +#define WGL_SWAP_UNDEFINED_EXT 0x202A +#define WGL_TYPE_RGBA_EXT 0x202B +#define WGL_TYPE_COLORINDEX_EXT 0x202C +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_DRAW_TO_PBUFFER_EXT 0x202D +#define WGL_MAX_PBUFFER_PIXELS_EXT 0x202E +#define WGL_MAX_PBUFFER_WIDTH_EXT 0x202F +#define WGL_MAX_PBUFFER_HEIGHT_EXT 0x2030 +#define WGL_OPTIMAL_PBUFFER_WIDTH_EXT 0x2031 +#define WGL_OPTIMAL_PBUFFER_HEIGHT_EXT 0x2032 +#define WGL_PBUFFER_LARGEST_EXT 0x2033 +#define WGL_PBUFFER_WIDTH_EXT 0x2034 +#define WGL_PBUFFER_HEIGHT_EXT 0x2035 +#endif + +#ifndef WGL_EXT_depth_float +#define WGL_DEPTH_FLOAT_EXT 0x2040 +#endif + +#ifndef WGL_3DFX_multisample +#define WGL_SAMPLE_BUFFERS_3DFX 0x2060 +#define WGL_SAMPLES_3DFX 0x2061 +#endif + +#ifndef WGL_EXT_multisample +#define WGL_SAMPLE_BUFFERS_EXT 0x2041 +#define WGL_SAMPLES_EXT 0x2042 +#endif + +#ifndef WGL_I3D_unknown_genlock_extension_name +#define WGL_GENLOCK_SOURCE_MULTIVIEW_I3D 0x2044 +#define WGL_GENLOCK_SOURCE_EXTENAL_SYNC_I3D 0x2045 +#define WGL_GENLOCK_SOURCE_EXTENAL_FIELD_I3D 0x2046 +#define WGL_GENLOCK_SOURCE_EXTENAL_TTL_I3D 0x2047 +#define WGL_GENLOCK_SOURCE_DIGITAL_SYNC_I3D 0x2048 +#define WGL_GENLOCK_SOURCE_DIGITAL_FIELD_I3D 0x2049 +#define WGL_GENLOCK_SOURCE_EDGE_FALLING_I3D 0x204A +#define WGL_GENLOCK_SOURCE_EDGE_RISING_I3D 0x204B +#define WGL_GENLOCK_SOURCE_EDGE_BOTH_I3D 0x204C +#endif + +#ifndef WGL_I3D_unknown_gamma_extension_name +#define WGL_GAMMA_TABLE_SIZE_I3D 0x204E +#define WGL_GAMMA_EXCLUDE_DESKTOP_I3D 0x204F +#endif + +#ifndef WGL_I3D_unknown_digital_video_cursor_extension_name +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_FRAMEBUFFER_I3D 0x2050 +#define WGL_DIGITAL_VIDEO_CURSOR_ALPHA_VALUE_I3D 0x2051 +#define WGL_DIGITAL_VIDEO_CURSOR_INCLUDED_I3D 0x2052 +#define WGL_DIGITAL_VIDEO_GAMMA_CORRECTED_I3D 0x2053 +#endif + + +/*************************************************************/ + +#ifndef WGL_ARB_pbuffer +DECLARE_HANDLE(HPBUFFERARB); +#endif +#ifndef WGL_EXT_pbuffer +DECLARE_HANDLE(HPBUFFEREXT); +#endif + +#ifndef WGL_ARB_buffer_region +#define WGL_ARB_buffer_region 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HANDLE WINAPI wglCreateBufferRegionARB (HDC, int, UINT); +extern VOID WINAPI wglDeleteBufferRegionARB (HANDLE); +extern BOOL WINAPI wglSaveBufferRegionARB (HANDLE, int, int, int, int); +extern BOOL WINAPI wglRestoreBufferRegionARB (HANDLE, int, int, int, int, int, int); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HANDLE (WINAPI * PFNWGLCREATEBUFFERREGIONARBPROC) (HDC hDC, int iLayerPlane, UINT uType); +typedef VOID (WINAPI * PFNWGLDELETEBUFFERREGIONARBPROC) (HANDLE hRegion); +typedef BOOL (WINAPI * PFNWGLSAVEBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height); +typedef BOOL (WINAPI * PFNWGLRESTOREBUFFERREGIONARBPROC) (HANDLE hRegion, int x, int y, int width, int height, int xSrc, int ySrc); +#endif + +#ifndef WGL_ARB_extensions_string +#define WGL_ARB_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringARB (HDC); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC) (HDC hdc); +#endif + +#ifndef WGL_ARB_pixel_format +#define WGL_ARB_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivARB (HDC, int, int, UINT, const int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvARB (HDC, int, int, UINT, const int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatARB (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVARBPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATARBPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_ARB_make_current_read +#define WGL_ARB_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentARB (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCARB (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTARBPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCARBPROC) (void); +#endif + +#ifndef WGL_ARB_pbuffer +#define WGL_ARB_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFERARB WINAPI wglCreatePbufferARB (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCARB (HPBUFFERARB); +extern int WINAPI wglReleasePbufferDCARB (HPBUFFERARB, HDC); +extern BOOL WINAPI wglDestroyPbufferARB (HPBUFFERARB); +extern BOOL WINAPI wglQueryPbufferARB (HPBUFFERARB, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFERARB (WINAPI * PFNWGLCREATEPBUFFERARBPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCARBPROC) (HPBUFFERARB hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFERARBPROC) (HPBUFFERARB hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFERARBPROC) (HPBUFFERARB hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_display_color_table +#define WGL_EXT_display_color_table 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern GLboolean WINAPI wglCreateDisplayColorTableEXT (GLushort); +extern GLboolean WINAPI wglLoadDisplayColorTableEXT (const GLushort *, GLuint); +extern GLboolean WINAPI wglBindDisplayColorTableEXT (GLushort); +extern VOID WINAPI wglDestroyDisplayColorTableEXT (GLushort); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef GLboolean (WINAPI * PFNWGLCREATEDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef GLboolean (WINAPI * PFNWGLLOADDISPLAYCOLORTABLEEXTPROC) (const GLushort *table, GLuint length); +typedef GLboolean (WINAPI * PFNWGLBINDDISPLAYCOLORTABLEEXTPROC) (GLushort id); +typedef VOID (WINAPI * PFNWGLDESTROYDISPLAYCOLORTABLEEXTPROC) (GLushort id); +#endif + +#ifndef WGL_EXT_extensions_string +#define WGL_EXT_extensions_string 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern const char * WINAPI wglGetExtensionsStringEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef const char * (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC) (void); +#endif + +#ifndef WGL_EXT_make_current_read +#define WGL_EXT_make_current_read 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglMakeContextCurrentEXT (HDC, HDC, HGLRC); +extern HDC WINAPI wglGetCurrentReadDCEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLMAKECONTEXTCURRENTEXTPROC) (HDC hDrawDC, HDC hReadDC, HGLRC hglrc); +typedef HDC (WINAPI * PFNWGLGETCURRENTREADDCEXTPROC) (void); +#endif + +#ifndef WGL_EXT_pbuffer +#define WGL_EXT_pbuffer 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern HPBUFFEREXT WINAPI wglCreatePbufferEXT (HDC, int, int, int, const int *); +extern HDC WINAPI wglGetPbufferDCEXT (HPBUFFEREXT); +extern int WINAPI wglReleasePbufferDCEXT (HPBUFFEREXT, HDC); +extern BOOL WINAPI wglDestroyPbufferEXT (HPBUFFEREXT); +extern BOOL WINAPI wglQueryPbufferEXT (HPBUFFEREXT, int, int *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef HPBUFFEREXT (WINAPI * PFNWGLCREATEPBUFFEREXTPROC) (HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList); +typedef HDC (WINAPI * PFNWGLGETPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer); +typedef int (WINAPI * PFNWGLRELEASEPBUFFERDCEXTPROC) (HPBUFFEREXT hPbuffer, HDC hDC); +typedef BOOL (WINAPI * PFNWGLDESTROYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer); +typedef BOOL (WINAPI * PFNWGLQUERYPBUFFEREXTPROC) (HPBUFFEREXT hPbuffer, int iAttribute, int *piValue); +#endif + +#ifndef WGL_EXT_pixel_format +#define WGL_EXT_pixel_format 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglGetPixelFormatAttribivEXT (HDC, int, int, UINT, int *, int *); +extern BOOL WINAPI wglGetPixelFormatAttribfvEXT (HDC, int, int, UINT, int *, FLOAT *); +extern BOOL WINAPI wglChoosePixelFormatEXT (HDC, const int *, const FLOAT *, UINT, int *, UINT *); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBFVEXTPROC) (HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, FLOAT *pfValues); +typedef BOOL (WINAPI * PFNWGLCHOOSEPIXELFORMATEXTPROC) (HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +#endif + +#ifndef WGL_EXT_swap_control +#define WGL_EXT_swap_control 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern BOOL WINAPI wglSwapIntervalEXT (int); +extern int WINAPI wglGetSwapIntervalEXT (void); +#endif /* WGL_WGLEXT_PROTOTYPES */ +typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval); +typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC) (void); +#endif + +#ifndef WGL_WGL_EXT_depth_float +#define WGL_WGL_EXT_depth_float 1 +#endif + +#ifndef WGL_WGL_3DFX_multisample +#define WGL_WGL_3DFX_multisample 1 +#endif + +#ifndef WGL_WGL_EXT_multisample +#define WGL_WGL_EXT_multisample 1 +#endif + +/* added by Cass -- but this should already be in here! */ +#ifndef WGL_NV_allocate_memory +#define WGL_NV_allocate_memory 1 +#ifdef WGL_WGLEXT_PROTOTYPES +extern void * wglAllocateMemoryNV(int size, float readfreq, float writefreq, float priority); +extern void wglFreeMemoryNV(void * pointer); +#endif +typedef void * (APIENTRY * PFNWGLALLOCATEMEMORYNVPROC) (int size, float readfreq, float writefreq, float priority); +typedef void (APIENTRY * PFNWGLFREEMEMORYNVPROC) (void *pointer); +#endif + + +#ifdef __cplusplus +} +#endif + +#endif + +