/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * This file is Copyright (C) 2007 - André Garneau (andre@pixdev.com) and licensed under OSGPL. * * Note, some elements of GraphicsWindowWin32 have used the Producer implementation as a reference. * These elements are licensed under OSGPL as above, with Copyright (C) 2001-2004 Don Burns. */ #include #include #include #include #include using namespace osgViewer; namespace osgViewer { // // Defines from the WGL_ARB_pixel_format specification document // See http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt // #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 #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 // // Entry points used from the WGL extensions // // BOOL wglChoosePixelFormatARB(HDC hdc, // const int *piAttribIList, // const FLOAT *pfAttribFList, // UINT nMaxFormats, // int *piFormats, // UINT *nNumFormats); // typedef bool (WINAPI * WGLChoosePixelFormatARB) ( HDC, const int *, const float *, unsigned int, int *, unsigned int * ); // // Utility class to specify the visual attributes for wglChoosePixelFormatARB() function // template class WGLAttributes { public: WGLAttributes() {} ~WGLAttributes() {} void begin() { m_parameters.clear(); } void set( const T& id, const T& value ) { add(id); add(value); } void enable( const T& id ) { add(id); add(true); } void disable( const T& id ) { add(id); add(false); } void end() { add(0); } const T* get() { return &m_parameters.front(); } protected: void add( const T& t ) { m_parameters.push_back(t); } std::vector m_parameters; // parameters added private: // No implementation for these WGLAttributes( const WGLAttributes& ); WGLAttributes& operator=( const WGLAttributes& ); }; typedef WGLAttributes WGLIntegerAttributes; typedef WGLAttributes WGLFloatAttributes; // // Class responsible for interfacing with the Win32 Window Manager // The behavior of this class is specific to OSG needs and is not a // generic Windowing interface. // // NOTE: This class is intended to be used by a single-thread. // Multi-threading is not enabled for performance reasons. // The creation/deletion of graphics windows should be done // by a single controller thread. That thread should then // call the checkEvents() method of all created windows periodically. // This is the case with OSG as a "main" thread does all // setup, update & event processing. Rendering is done (optionally) by other threads. // // !@todo Have a dedicated thread managed by the Win32WindowingSystem class handle the // creation and event message processing for all windows it manages. This // is to relieve the "main" thread from having to do this synchronously // during frame generation. The "main" thread would only have to process // each osgGA-type window event queue. // class Win32WindowingSystem : public osg::GraphicsContext::WindowingSystemInterface { public: static std::string osgGraphicsWindowClassName; //!< Name of Win32 window class used by OSG graphics window instances Win32WindowingSystem(); ~Win32WindowingSystem(); // Access the Win32 windowing system through this singleton class. static Win32WindowingSystem* getInterface() { static Win32WindowingSystem* win32Interface = new Win32WindowingSystem; return win32Interface; } // Return the number of screens present in the system virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si ); // Return the resolution of specified screen // (0,0) is returned if screen is unknown virtual void getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height ); // Return the screen position and width/height. // all zeros returned if screen is unknown virtual void getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height ); // Create a graphics context with given traits virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ); // Register a newly created native window along with its application counterpart // This is required to maintain a link between Windows messages and the application window object // at event processing time virtual void registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window ); // Unregister a window // This is called as part of a window being torn down virtual void unregisterWindow( HWND hwnd ); // Get the application window object associated with a native window virtual osgViewer::GraphicsWindowWin32* getGraphicsWindowFor( HWND hwnd ); // Return a valid sample OpenGL Device Context and Rendering Context that can be used with wglXYZ extensions virtual void getSampleOpenGLContext( HDC& deviceContext, HGLRC& renderingContext ); protected: // Display devices present in the system typedef std::vector DisplayDevices; // Map Win32 window handles to GraphicsWindowWin32 instance typedef std::pair< HWND, osgViewer::GraphicsWindowWin32* > WindowHandleEntry; typedef std::map< HWND, osgViewer::GraphicsWindowWin32* > WindowHandles; // Enumerate all display devices and return in passed container void enumerateDisplayDevices( DisplayDevices& displayDevices ) const; bool getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DEVMODE& deviceMode ); // Register the window class used by OSG graphics window instances void registerWindowClass(); // Unregister the window class used by OSG graphics window instances void unregisterWindowClass(); // Release sample GL context void releaseSampleOpenGLContext(); // Data members WindowHandles _activeWindows; //!< handles to active windows HWND _dummyGLWindow; //!< dummy GL window used to provide a valid context for wglXYZ calls HDC _dummyGLWindowDC; //!< dummy GL window device context HGLRC _dummyGLRC; //!< dummy GL rendering context bool _windowClassRegistered; //!< true after windowing interface has been initialized successfully private: // No implementation for these Win32WindowingSystem( const Win32WindowingSystem& ); Win32WindowingSystem& operator=( const Win32WindowingSystem& ); }; // // This is the class we need to create for pbuffers and display devices that are not attached to the desktop // (and thus cannot have windows created on their surface). // // Note its not a GraphicsWindow as it won't need any of the event handling and window mapping facilities. // class GraphicsContextWin32 : public osg::GraphicsContext { public: GraphicsContextWin32(osg::GraphicsContext::Traits* traits); ~GraphicsContextWin32(); virtual bool valid() const; /** Realise the GraphicsContext implementation, * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool realizeImplementation(); /** Return true if the graphics context has been realised, and is ready to use, implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool isRealizedImplementation() const; /** Close the graphics context implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual void closeImplementation(); /** Make this graphics context current implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool makeCurrentImplementation(); /** Make this graphics context current with specified read context implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual bool makeContextCurrentImplementation(GraphicsContext* /*readContext*/); /** Release the graphics context.*/ virtual bool releaseContextImplementation(); /** Pure virtual, Bind the graphics context to associated texture implementation. * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ virtual void bindPBufferToTextureImplementation(GLenum /*buffer*/); /** Swap the front and back buffers implementation. * Pure virtual - must be implemented by Concrate implementations of GraphicsContext. */ virtual void swapBuffersImplementation(); protected: bool _valid; }; ////////////////////////////////////////////////////////////////////////////// // Error reporting ////////////////////////////////////////////////////////////////////////////// static void reportError( const std::string& msg, unsigned int errorCode ) { osg::notify(osg::WARN) << "Windows System Error #" << errorCode << " : " << msg.c_str(); LPVOID lpMsgBuf; if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, 0, // Default language (LPTSTR) &lpMsgBuf, 0, NULL)!=0) { osg::notify(osg::WARN) << ". Reason : " << LPTSTR(lpMsgBuf) << std::endl; ::LocalFree(lpMsgBuf); } else { osg::notify(osg::WARN) << std::endl; } } static void reportError( const std::string& msg ) { osg::notify(osg::WARN) << "Error: " << msg.c_str() << std::endl; } ////////////////////////////////////////////////////////////////////////////// // Keyboard key mapping for Win32 ////////////////////////////////////////////////////////////////////////////// class Win32KeyboardMap { public: Win32KeyboardMap() { _keymap[VK_ESCAPE ] = osgGA::GUIEventAdapter::KEY_Escape; _keymap[VK_F1 ] = osgGA::GUIEventAdapter::KEY_F1; _keymap[VK_F2 ] = osgGA::GUIEventAdapter::KEY_F2; _keymap[VK_F3 ] = osgGA::GUIEventAdapter::KEY_F3; _keymap[VK_F4 ] = osgGA::GUIEventAdapter::KEY_F4; _keymap[VK_F5 ] = osgGA::GUIEventAdapter::KEY_F5; _keymap[VK_F6 ] = osgGA::GUIEventAdapter::KEY_F6; _keymap[VK_F7 ] = osgGA::GUIEventAdapter::KEY_F7; _keymap[VK_F8 ] = osgGA::GUIEventAdapter::KEY_F8; _keymap[VK_F9 ] = osgGA::GUIEventAdapter::KEY_F9; _keymap[VK_F10 ] = osgGA::GUIEventAdapter::KEY_F10; _keymap[VK_F11 ] = osgGA::GUIEventAdapter::KEY_F11; _keymap[VK_F12 ] = osgGA::GUIEventAdapter::KEY_F12; _keymap[0xc0 ] = '`'; _keymap['0' ] = '0'; _keymap['1' ] = '1'; _keymap['2' ] = '2'; _keymap['3' ] = '3'; _keymap['4' ] = '4'; _keymap['5' ] = '5'; _keymap['6' ] = '6'; _keymap['7' ] = '7'; _keymap['8' ] = '8'; _keymap['9' ] = '9'; _keymap[0xbd ] = '-'; _keymap[0xbb ] = '='; _keymap[VK_BACK ] = osgGA::GUIEventAdapter::KEY_BackSpace; _keymap[VK_TAB ] = osgGA::GUIEventAdapter::KEY_Tab; _keymap['A' ] = 'A'; _keymap['B' ] = 'B'; _keymap['C' ] = 'C'; _keymap['D' ] = 'D'; _keymap['E' ] = 'E'; _keymap['F' ] = 'F'; _keymap['G' ] = 'G'; _keymap['H' ] = 'H'; _keymap['I' ] = 'I'; _keymap['J' ] = 'J'; _keymap['K' ] = 'K'; _keymap['L' ] = 'L'; _keymap['M' ] = 'M'; _keymap['N' ] = 'N'; _keymap['O' ] = 'O'; _keymap['P' ] = 'P'; _keymap['Q' ] = 'Q'; _keymap['R' ] = 'R'; _keymap['S' ] = 'S'; _keymap['T' ] = 'T'; _keymap['U' ] = 'U'; _keymap['V' ] = 'V'; _keymap['W' ] = 'W'; _keymap['X' ] = 'X'; _keymap['Y' ] = 'Y'; _keymap['Z' ] = 'Z'; _keymap[0xdb ] = '['; _keymap[0xdd ] = ']'; _keymap[0xdc ] = '\\'; _keymap[VK_CAPITAL ] = osgGA::GUIEventAdapter::KEY_Caps_Lock; _keymap[0xba ] = ';'; _keymap[0xde ] = '\''; _keymap[VK_RETURN ] = osgGA::GUIEventAdapter::KEY_Return; _keymap[VK_LSHIFT ] = osgGA::GUIEventAdapter::KEY_Shift_L; _keymap[0xbc ] = ','; _keymap[0xbe ] = '.'; _keymap[0xbf ] = '/'; _keymap[VK_RSHIFT ] = osgGA::GUIEventAdapter::KEY_Shift_R; _keymap[VK_LCONTROL ] = osgGA::GUIEventAdapter::KEY_Control_L; _keymap[VK_LWIN ] = osgGA::GUIEventAdapter::KEY_Super_L; _keymap[VK_SPACE ] = ' '; _keymap[VK_LMENU ] = osgGA::GUIEventAdapter::KEY_Alt_L; _keymap[VK_RMENU ] = osgGA::GUIEventAdapter::KEY_Alt_R; _keymap[VK_RWIN ] = osgGA::GUIEventAdapter::KEY_Super_R; _keymap[VK_APPS ] = osgGA::GUIEventAdapter::KEY_Menu; _keymap[VK_RCONTROL ] = osgGA::GUIEventAdapter::KEY_Control_R; _keymap[VK_SNAPSHOT ] = osgGA::GUIEventAdapter::KEY_Print; _keymap[VK_SCROLL ] = osgGA::GUIEventAdapter::KEY_Scroll_Lock; _keymap[VK_PAUSE ] = osgGA::GUIEventAdapter::KEY_Pause; _keymap[VK_HOME ] = osgGA::GUIEventAdapter::KEY_Home; _keymap[VK_PRIOR ] = osgGA::GUIEventAdapter::KEY_Page_Up; _keymap[VK_END ] = osgGA::GUIEventAdapter::KEY_End; _keymap[VK_NEXT ] = osgGA::GUIEventAdapter::KEY_Page_Down; _keymap[VK_DELETE ] = osgGA::GUIEventAdapter::KEY_Delete; _keymap[VK_INSERT ] = osgGA::GUIEventAdapter::KEY_Insert; _keymap[VK_LEFT ] = osgGA::GUIEventAdapter::KEY_Left; _keymap[VK_UP ] = osgGA::GUIEventAdapter::KEY_Up; _keymap[VK_RIGHT ] = osgGA::GUIEventAdapter::KEY_Right; _keymap[VK_DOWN ] = osgGA::GUIEventAdapter::KEY_Down; _keymap[VK_NUMLOCK ] = osgGA::GUIEventAdapter::KEY_Num_Lock; _keymap[VK_DIVIDE ] = osgGA::GUIEventAdapter::KEY_KP_Divide; _keymap[VK_MULTIPLY ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; _keymap[VK_SUBTRACT ] = osgGA::GUIEventAdapter::KEY_KP_Subtract; _keymap[VK_ADD ] = osgGA::GUIEventAdapter::KEY_KP_Add; _keymap[VK_NUMPAD7 ] = osgGA::GUIEventAdapter::KEY_KP_Home; _keymap[VK_NUMPAD8 ] = osgGA::GUIEventAdapter::KEY_KP_Up; _keymap[VK_NUMPAD9 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; _keymap[VK_NUMPAD4 ] = osgGA::GUIEventAdapter::KEY_KP_Left; _keymap[VK_NUMPAD5 ] = osgGA::GUIEventAdapter::KEY_KP_Begin; _keymap[VK_NUMPAD6 ] = osgGA::GUIEventAdapter::KEY_KP_Right; _keymap[VK_NUMPAD1 ] = osgGA::GUIEventAdapter::KEY_KP_End; _keymap[VK_NUMPAD2 ] = osgGA::GUIEventAdapter::KEY_KP_Down; _keymap[VK_NUMPAD3 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; _keymap[VK_NUMPAD0 ] = osgGA::GUIEventAdapter::KEY_KP_Insert; _keymap[VK_DECIMAL ] = osgGA::GUIEventAdapter::KEY_KP_Delete; } ~Win32KeyboardMap() {} int remapKey(int key) { KeyMap::const_iterator map = _keymap.find(key); return map==_keymap.end() ? key : map->second; } protected: typedef std::map KeyMap; KeyMap _keymap; }; static Win32KeyboardMap s_win32KeyboardMap; static int remapWin32Key(int key) { return s_win32KeyboardMap.remapKey(key); } ////////////////////////////////////////////////////////////////////////////// // Window procedure for all GraphicsWindowWin32 instances // Dispatches the call to the actual instance ////////////////////////////////////////////////////////////////////////////// static LRESULT CALLBACK WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { osgViewer::GraphicsWindowWin32* window = Win32WindowingSystem::getInterface()->getGraphicsWindowFor(hwnd); return window ? window->handleNativeWindowingEvent(hwnd, uMsg, wParam, lParam) : ::DefWindowProc(hwnd, uMsg, wParam, lParam); } ////////////////////////////////////////////////////////////////////////////// // Win32WindowingSystem implementation ////////////////////////////////////////////////////////////////////////////// std::string Win32WindowingSystem::osgGraphicsWindowClassName; Win32WindowingSystem::Win32WindowingSystem() : _dummyGLWindow(0), _dummyGLWindowDC(0), _dummyGLRC(0), _windowClassRegistered(false) { } Win32WindowingSystem::~Win32WindowingSystem() { releaseSampleOpenGLContext(); unregisterWindowClass(); } void Win32WindowingSystem::enumerateDisplayDevices( DisplayDevices& displayDevices ) const { for (unsigned int deviceNum=0;; ++deviceNum) { DISPLAY_DEVICE displayDevice; displayDevice.cb = sizeof(displayDevice); if (!::EnumDisplayDevices(NULL, deviceNum, &displayDevice, 0)) break; // Do not track devices used for remote access (Terminal Services pseudo-displays, etc.) if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; //!@todo when the GraphicsContextWin32 class is implemented, remove this line // For the time-being only return display devices that are attached to the desktop if (!(displayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) continue; displayDevices.push_back(displayDevice); } } void Win32WindowingSystem::registerWindowClass() { if (_windowClassRegistered) return; // // Register the window class used by OSG GraphicsWindowWin32 instances // std::ostringstream str; str << "OpenSceneGraph Graphics Window for Win32 [" << ::GetCurrentProcessId() << "]"; osgGraphicsWindowClassName = str.str(); WNDCLASSEX wc; HINSTANCE hinst = ::GetModuleHandle(NULL); wc.cbSize = sizeof(wc); wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hinst; wc.hIcon = ::LoadIcon(hinst, "OSG_ICON"); wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = NULL; wc.lpszMenuName = 0; wc.lpszClassName = osgGraphicsWindowClassName.c_str(); wc.hIconSm = NULL; if (::RegisterClassEx(&wc)==0) { unsigned int lastError = ::GetLastError(); if (lastError!=ERROR_CLASS_ALREADY_EXISTS) { reportError("Win32WindowingSystem::registerWindowClass() - Unable to register window class", lastError); return; } } _windowClassRegistered = true; } void Win32WindowingSystem::unregisterWindowClass() { if (_windowClassRegistered) { ::UnregisterClass(osgGraphicsWindowClassName.c_str(), ::GetModuleHandle(NULL)); _windowClassRegistered = false; } } void Win32WindowingSystem::getSampleOpenGLContext( HDC& deviceContext, HGLRC& renderingContext ) { deviceContext = _dummyGLWindowDC; renderingContext = _dummyGLRC; if (_dummyGLWindowDC) return; registerWindowClass(); HWND hwnd = ::CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, osgGraphicsWindowClassName.c_str(), NULL, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED, 0, 0, 256, 256, NULL, NULL, ::GetModuleHandle(NULL), NULL); if (hwnd==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create window", ::GetLastError()); return; } // // Set the pixel format of the window // PIXELFORMATDESCRIPTOR pixelFormat = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0 }; HDC hdc = ::GetDC(hwnd); if (hdc==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to get window device context", ::GetLastError()); ::DestroyWindow(hwnd); return; } int pixelFormatIndex = ::ChoosePixelFormat(hdc, &pixelFormat); if (pixelFormatIndex==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to choose pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return; } if (!::SetPixelFormat(hdc, pixelFormatIndex, &pixelFormat)) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to set pixel format", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return; } HGLRC hglrc = ::wglCreateContext(hdc); if (hglrc==0) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to create an OpenGL rendering context", ::GetLastError()); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return; } if (!::wglMakeCurrent(hdc, hglrc)) { reportError("Win32WindowingSystem::getSampleOpenGLContext() - Unable to set the OpenGL rendering context", ::GetLastError()); ::wglDeleteContext(hglrc); ::ReleaseDC(hwnd, hdc); ::DestroyWindow(hwnd); return; } _dummyGLWindow = hwnd; _dummyGLWindowDC = hdc; _dummyGLRC = hglrc; deviceContext = _dummyGLWindowDC; renderingContext = _dummyGLRC; } void Win32WindowingSystem::releaseSampleOpenGLContext() { if (_dummyGLRC) { ::wglMakeCurrent(_dummyGLWindowDC, NULL); ::wglDeleteContext(_dummyGLRC); _dummyGLRC = 0; } if (_dummyGLWindowDC) { ::ReleaseDC(_dummyGLWindow, _dummyGLWindowDC); _dummyGLWindowDC = 0; } if (_dummyGLWindow) { ::DestroyWindow(_dummyGLWindow); _dummyGLWindow = 0; } } unsigned int Win32WindowingSystem::getNumScreens( const osg::GraphicsContext::ScreenIdentifier& si ) { //!@todo change when implementing the GraphicsContextWin32 class. return si.displayNum==0 ? ::GetSystemMetrics(SM_CMONITORS) : 0; } bool Win32WindowingSystem::getScreenInformation( const osg::GraphicsContext::ScreenIdentifier& si, DEVMODE& deviceMode ) { if (si.displayNum>0) { osg::notify(osg::WARN) << "Win32WindowingSystem::getScreenInformation() - The screen identifier on the Win32 platform must always use display number 0. Value received was " << si.displayNum << std::endl; return false; } DisplayDevices displayDevices; enumerateDisplayDevices(displayDevices); if (si.screenNum>=displayDevices.size()) { osg::notify(osg::WARN) << "Win32WindowingSystem::getScreenInformation() - Cannot get information for screen " << si.screenNum << " because it does not exist." << std::endl; return false; } deviceMode.dmSize = sizeof(deviceMode); deviceMode.dmDriverExtra = 0; if (!::EnumDisplaySettings(displayDevices[si.screenNum].DeviceName, ENUM_CURRENT_SETTINGS, &deviceMode)) { std::ostringstream str; str << "Win32WindowingSystem::getScreenInformation() - Unable to query information for screen number " << si.screenNum; reportError(str.str(), ::GetLastError()); return false; } return true; } void Win32WindowingSystem::getScreenResolution( const osg::GraphicsContext::ScreenIdentifier& si, unsigned int& width, unsigned int& height ) { DEVMODE deviceMode; if (getScreenInformation(si, deviceMode)) { width = deviceMode.dmPelsWidth; height = deviceMode.dmPelsHeight; } else { width = 0; height = 0; } } void Win32WindowingSystem::getScreenPosition( const osg::GraphicsContext::ScreenIdentifier& si, int& originX, int& originY, unsigned int& width, unsigned int& height ) { DEVMODE deviceMode; if (getScreenInformation(si, deviceMode)) { originX = deviceMode.dmPosition.x; originY = deviceMode.dmPosition.y; width = deviceMode.dmPelsWidth; height = deviceMode.dmPelsHeight; } else { originX = 0; originY = 0; width = 0; height = 0; } } osg::GraphicsContext* Win32WindowingSystem::createGraphicsContext( osg::GraphicsContext::Traits* traits ) { if (traits->pbuffer) { osg::ref_ptr pbuffer = new GraphicsContextWin32(traits); if (pbuffer->valid()) return pbuffer.release(); else return 0; } else { registerWindowClass(); osg::ref_ptr window = new GraphicsWindowWin32(traits); if (window->valid()) return window.release(); else return 0; } } void Win32WindowingSystem::registerWindow( HWND hwnd, osgViewer::GraphicsWindowWin32* window ) { if (hwnd) _activeWindows.insert(WindowHandleEntry(hwnd, window)); } // // Unregister a window // This is called as part of a window being torn down // void Win32WindowingSystem::unregisterWindow( HWND hwnd ) { if (hwnd) _activeWindows.erase(hwnd); } // // Get the application window object associated with a native window // osgViewer::GraphicsWindowWin32* Win32WindowingSystem::getGraphicsWindowFor( HWND hwnd ) { WindowHandles::const_iterator entry = _activeWindows.find(hwnd); return entry==_activeWindows.end() ? 0 : entry->second; } ////////////////////////////////////////////////////////////////////////////// // GraphicsWindowWin32 implementation ////////////////////////////////////////////////////////////////////////////// GraphicsWindowWin32::GraphicsWindowWin32( osg::GraphicsContext::Traits* traits ) : _hwnd(0), _hdc(0), _hglrc(0), _timeOfLastCheckEvents(-1.0), _screenOriginX(0), _screenOriginY(0), _screenWidth(0), _screenHeight(0), _windowOriginXToRealize(0), _windowOriginYToRealize(0), _windowWidthToRealize(0), _windowHeightToRealize(0), _initialized(false), _valid(false), _realized(false), _destroying(false) { _traits = traits; init(); if (valid()) { setState( new osg::State ); getState()->setContextID( osg::GraphicsContext::createNewContextID() ); Win32WindowingSystem::getInterface()->registerWindow(_hwnd, this); } } GraphicsWindowWin32::~GraphicsWindowWin32() { close(); destroyWindow(); } void GraphicsWindowWin32::init() { if (!_initialized) { _initialized = createWindow() != 0; _valid = _initialized; } } HWND GraphicsWindowWin32::createWindow() { unsigned int extendedStyle; unsigned int windowStyle; if (!determineWindowPositionAndStyle(_traits->windowDecoration, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, windowStyle, extendedStyle)) { reportError("GraphicsWindowWin32::createWindow() - Unable to determine the window position and style"); return 0; } _hwnd = ::CreateWindowEx(extendedStyle, Win32WindowingSystem::osgGraphicsWindowClassName.c_str(), _traits->windowName.c_str(), windowStyle, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, NULL, NULL, ::GetModuleHandle(NULL), NULL); if (_hwnd==0) { reportError("GraphicsWindowWin32::createWindow() - Unable to create window", ::GetLastError()); return 0; } _hdc = ::GetDC(_hwnd); if (_hdc==0) { reportError("GraphicsWindowWin32::createWindow() - Unable to get window device context", ::GetLastError()); destroyWindow(); _hwnd = 0; return 0; } // // Set the pixel format according to traits specified // if (!setPixelFormat()) { ::ReleaseDC(_hwnd, _hdc); _hdc = 0; destroyWindow(); return 0; } return _hwnd; } void GraphicsWindowWin32::destroyWindow( bool deleteNativeWindow ) { if (_destroying) return; _destroying = true; close(); if (_hdc) { releaseContext(); if (_hglrc) { ::wglDeleteContext(_hglrc); _hglrc = 0; } ::ReleaseDC(_hwnd, _hdc); _hdc = 0; } if (_hwnd) { Win32WindowingSystem::getInterface()->unregisterWindow(_hwnd); if (deleteNativeWindow) ::DestroyWindow(_hwnd); _hwnd = 0; } _initialized = false; _realized = false; _valid = false; } bool GraphicsWindowWin32::determineWindowPositionAndStyle( bool decorated, int& x, int& y, unsigned int& w, unsigned int& h, unsigned int& style, unsigned int& extendedStyle ) { if (_traits==0) return false; // // Query the screen position and size // osg::GraphicsContext::ScreenIdentifier screenId(_traits->screenNum); Win32WindowingSystem* windowManager = Win32WindowingSystem::getInterface(); windowManager->getScreenPosition(screenId, _screenOriginX, _screenOriginY, _screenWidth, _screenHeight); if (_screenWidth==0 || _screenHeight==0) return 0; x = _traits->x + _screenOriginX; y = _traits->y + _screenOriginY; w = _traits->width; h = _traits->height; style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; extendedStyle = 0; if (decorated) { style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; if (_traits->supportsResize) style |= WS_SIZEBOX; extendedStyle = WS_EX_APPWINDOW | WS_EX_OVERLAPPEDWINDOW | WS_EX_ACCEPTFILES | WS_EX_LTRREADING; RECT corners; corners.left = x; corners.top = y; corners.right = x + w - 1; corners.bottom = y + h - 1; // // Determine the location of the window corners in order to have // a client area of the requested size // if (!::AdjustWindowRectEx(&corners, style, FALSE, extendedStyle)) { reportError("GraphicsWindowWin32::determineWindowPositionAndStyle() - Unable to adjust window rectangle", ::GetLastError()); return false; } x = corners.left; y = corners.top; w = corners.right - corners.left + 1; h = corners.bottom - corners.top + 1; } return true; } bool GraphicsWindowWin32::setPixelFormat() { HDC hdc; HGLRC hglrc; Win32WindowingSystem::getInterface()->getSampleOpenGLContext(hdc, hglrc); // // Access the entry point for the wglChoosePixelFormatARB function // WGLChoosePixelFormatARB wglChoosePixelFormatARB = (WGLChoosePixelFormatARB)wglGetProcAddress("wglChoosePixelFormatARB"); if (wglChoosePixelFormatARB==0) { reportError("GraphicsWindowWin32::setPixelFormat() - wglChoosePixelFormatARB extension not found", ::GetLastError()); return false; } // // Build the specifications of the requested pixel format // WGLIntegerAttributes attributes; attributes.begin(); attributes.enable(WGL_DRAW_TO_WINDOW_ARB); attributes.enable(WGL_SUPPORT_OPENGL_ARB); attributes.set(WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB); attributes.set(WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB); attributes.set(WGL_COLOR_BITS_ARB, _traits->red + _traits->green + _traits->blue); attributes.set(WGL_RED_BITS_ARB, _traits->red); attributes.set(WGL_GREEN_BITS_ARB, _traits->green); attributes.set(WGL_BLUE_BITS_ARB, _traits->blue); attributes.set(WGL_DEPTH_BITS_ARB, _traits->depth); if (_traits->doubleBuffer) { attributes.enable(WGL_DOUBLE_BUFFER_ARB); attributes.set(WGL_SWAP_METHOD_ARB, WGL_SWAP_EXCHANGE_ARB); } if (_traits->alpha) attributes.set(WGL_ALPHA_BITS_ARB, _traits->alpha); if (_traits->stencil) attributes.set(WGL_STENCIL_BITS_ARB, _traits->stencil); if (_traits->sampleBuffers) attributes.set(WGL_SAMPLE_BUFFERS_ARB, _traits->sampleBuffers); if (_traits->samples) attributes.set(WGL_SAMPLES_ARB, _traits->samples); if (_traits->quadBufferStereo) attributes.enable(WGL_STEREO_ARB); attributes.end(); // // Choose the closest pixel format from the specified traits // int pixelFormatIndex = 0; unsigned int numMatchingPixelFormats = 0; if (!wglChoosePixelFormatARB(hdc, attributes.get(), NULL, 1, &pixelFormatIndex, &numMatchingPixelFormats)) { reportError("GraphicsWindowWin32::setPixelFormat() - Unable to choose the requested pixel format", ::GetLastError()); return false; } if (numMatchingPixelFormats==0) { reportError("GraphicsWindowWin32::setPixelFormat() - No matching pixel format found based on traits specified", ::GetLastError()); return false; } // // Set the pixel format found // PIXELFORMATDESCRIPTOR pfd; ::memset(&pfd, 0, sizeof(pfd)); pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion = 1; if (!::SetPixelFormat(_hdc, pixelFormatIndex, &pfd)) { reportError("GraphicsWindowWin32::setPixelFormat() - Unable to set pixel format", ::GetLastError()); return false; } // // Create the OpenGL rendering context associated with this window // _hglrc = ::wglCreateContext(_hdc); if (_hglrc==0) { reportError("GraphicsWindowWin32::setPixelFormat() - Unable to create OpenGL rendering context", ::GetLastError()); return false; } return true; } void GraphicsWindowWin32::setWindowDecoration( bool decorated ) { unsigned int windowStyle; unsigned int extendedStyle; // // Determine position and size of window with/without decorations to retain the size specified in traits // int x, y; unsigned int w, h; if (!determineWindowPositionAndStyle(decorated, x, y, w, h, windowStyle, extendedStyle)) { reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to determine the window position and style"); return; } // // Change the window style // ::SetLastError(0); unsigned int result = ::SetWindowLong(_hwnd, GWL_STYLE, windowStyle); unsigned int error = ::GetLastError(); if (result==0 && error) { reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set window style", error); return; } // // Change the window extended style // ::SetLastError(0); result = ::SetWindowLong(_hwnd, GWL_EXSTYLE, extendedStyle); error = ::GetLastError(); if (result==0 && error) { reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set window extented style", error); return; } // // Change the window position and size and realize the style changes // if (!::SetWindowPos(_hwnd, HWND_TOP, x, y, w, h, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_SHOWWINDOW)) { reportError("GraphicsWindowWin32::setWindowDecoration() - Unable to set new window position and size", ::GetLastError()); return; } // // Repaint the desktop to cleanup decorations removed // if (!decorated) { ::InvalidateRect(NULL, NULL, TRUE); } } bool GraphicsWindowWin32::realizeImplementation() { if (_realized) return true; if (!_initialized) { init(); if (!_initialized) return false; } // // Bring the window on top of other ones (including the taskbar if it covers it completely) // // NOTE: To cover the taskbar with a window that does not completely cover it, the HWND_TOPMOST // Z-order must be used in the code below instead of HWND_TOP. // @todo: This should be controlled through a flag in the traits (topMostWindow) // if (!::SetWindowPos(_hwnd, HWND_TOP, _windowOriginXToRealize, _windowOriginYToRealize, _windowWidthToRealize, _windowHeightToRealize, SWP_SHOWWINDOW)) { reportError("GraphicsWindowWin32::realizeImplementation() - Unable to show window", ::GetLastError()); return false; } if (!::UpdateWindow(_hwnd)) { reportError("GraphicsWindowWin32::realizeImplementation() - Unable to update window", ::GetLastError()); return false; } _realized = true; return true; } bool GraphicsWindowWin32::makeCurrentImplementation() { if (!_realized) { reportError("GraphicsWindowWin32::makeCurrentImplementation() - Window not realized; cannot do makeCurrent."); return false; } if (!::wglMakeCurrent(_hdc, _hglrc)) { reportError("GraphicsWindowWin32::makeCurrentImplementation() - Unable to set current OpenGL rendering context", ::GetLastError()); return false; } return true; } bool GraphicsWindowWin32::releaseContextImplementation() { if (!::wglMakeCurrent(_hdc, NULL)) { reportError("GraphicsWindowWin32::releaseContextImplementation() - Unable to release current OpenGL rendering context", ::GetLastError()); return false; } return true; } void GraphicsWindowWin32::closeImplementation() { destroyWindow(); _initialized = false; _valid = false; _realized = false; } void GraphicsWindowWin32::swapBuffersImplementation() { if (!_realized) return; if (!::SwapBuffers(_hdc)) { reportError("GraphicsWindowWin32::swapBuffersImplementation() - Unable to swap display buffers", ::GetLastError()); } } void GraphicsWindowWin32::checkEvents() { if (!_realized) return; MSG msg; while (::PeekMessage(&msg, _hwnd, NULL, NULL, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } } void GraphicsWindowWin32::grabFocus() { if (!::SetForegroundWindow(_hwnd)) { osg::notify(osg::WARN) << "Warning: GraphicsWindowWin32::grabFocus() - Failed grabbing the focus" << std::endl; } } void GraphicsWindowWin32::grabFocusIfPointerInWindow() { POINT mousePos; if (!::GetCursorPos(&mousePos)) { reportError("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get cursor position", ::GetLastError()); return; } RECT windowRect; if (!::GetWindowRect(_hwnd, &windowRect)) { reportError("GraphicsWindowWin32::grabFocusIfPointerInWindow() - Unable to get window position", ::GetLastError()); return; } if (mousePos.x>=windowRect.left && mousePos.x<=windowRect.right && mousePos.y>=windowRect.top && mousePos.y<=windowRect.bottom) { grabFocus(); } } void GraphicsWindowWin32::adaptKey( WPARAM wParam, LPARAM lParam, int& keySymbol, unsigned int& modifierMask ) { modifierMask = 0; BYTE keyState[256]; if (!::GetKeyboardState(keyState)) { keySymbol = 0; return; } bool rightSide = (lParam & 0x01000000)!=0; if (keyState[VK_SHIFT] & 0x80) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_SHIFT; modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT : osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT; } if (keyState[VK_CAPITAL] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_CAPS_LOCK; if (keyState[VK_NUMLOCK] & 0x01) modifierMask |= osgGA::GUIEventAdapter::MODKEY_NUM_LOCK; if (keyState[VK_CONTROL] & 0x80) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_CTRL; modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL : osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL; } if (lParam & 0x20000000) { modifierMask |= osgGA::GUIEventAdapter::MODKEY_LEFT_ALT; modifierMask |= rightSide ? osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT : osgGA::GUIEventAdapter::MODKEY_LEFT_ALT; } keySymbol = remapWin32Key(wParam); if (keySymbol==osgGA::GUIEventAdapter::KEY_Return && rightSide) { keySymbol = osgGA::GUIEventAdapter::KEY_KP_Enter; } else if ((keySymbol & 0xff00)==0) { char asciiKey[2]; int numChars = ::ToAscii(wParam, (lParam>>16)&0xff, keyState, reinterpret_cast(asciiKey), 0); if (numChars>0) keySymbol = asciiKey[0]; } } void GraphicsWindowWin32::transformMouseXY( float& x, float& y ) { if (getEventQueue()->getUseFixedMouseInputRange()) { osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState(); x = eventState->getXmin() + (eventState->getXmax()-eventState->getXmin())*x/float(_traits->width); y = eventState->getYmin() + (eventState->getYmax()-eventState->getYmin())*y/float(_traits->height); } } LRESULT GraphicsWindowWin32::handleNativeWindowingEvent( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { //!@todo adapt windows event time to osgGA event queue time for better resolution double baseTime = _timeOfLastCheckEvents; double eventTime = _timeOfLastCheckEvents; double resizeTime = eventTime; _timeOfLastCheckEvents = getEventQueue()->getTime(); switch(uMsg) { ///////////////// case WM_PAINT : ///////////////// { PAINTSTRUCT paint; ::BeginPaint(hwnd, &paint); ::EndPaint(hwnd, &paint); } break; /////////////////// case WM_MOUSEMOVE : /////////////////// { float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseMotion(mx, my, eventTime); } break; ///////////////////// case WM_LBUTTONDOWN : case WM_MBUTTONDOWN : case WM_RBUTTONDOWN : ///////////////////// { int button; if (uMsg==WM_LBUTTONDOWN) button = 1; else if (uMsg==WM_MBUTTONDOWN) button = 2; else button = 3; float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseButtonPress(mx, my, button, eventTime); } break; ///////////////////// case WM_LBUTTONUP : case WM_MBUTTONUP : case WM_RBUTTONUP : ///////////////////// { int button; if (uMsg==WM_LBUTTONUP) button = 1; else if (uMsg==WM_MBUTTONUP) button = 2; else button = 3; float mx = GET_X_LPARAM(lParam); float my = GET_Y_LPARAM(lParam); transformMouseXY(mx, my); getEventQueue()->mouseButtonRelease(mx, my, button, eventTime); } break; //////////////////// case WM_MOUSEWHEEL : //////////////////// getEventQueue()->mouseScroll(GET_WHEEL_DELTA_WPARAM(wParam)<0 ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP, eventTime); break; ///////////////// case WM_MOVE : case WM_SIZE : ///////////////// { POINT origin; origin.x = 0; origin.y = 0; ::ClientToScreen(hwnd, &origin); int windowX = origin.x - _screenOriginX; int windowY = origin.y - _screenOriginY; resizeTime = eventTime; RECT clientRect; ::GetClientRect(hwnd, &clientRect); int windowWidth; int windowHeight; if (clientRect.bottom==0 && clientRect.right==0) { // // Window has been minimized; keep window width & height to a minimum of 1 pixel // windowWidth = 1; windowHeight = 1; } else { windowWidth = clientRect.right; windowHeight = clientRect.bottom; } if (windowX!=_traits->x || windowY!=_traits->y || windowWidth!=_traits->width || windowHeight!=_traits->height) { resized(windowX, windowY, windowWidth, windowHeight); getEventQueue()->windowResize(windowX, windowY, windowWidth, windowHeight, resizeTime); } } break; //////////////////// case WM_KEYDOWN : case WM_SYSKEYDOWN : //////////////////// { int keySymbol = 0; unsigned int modifierMask = 0; adaptKey(wParam, lParam, keySymbol, modifierMask); getEventQueue()->keyPress(keySymbol, eventTime); getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); } break; ////////////////// case WM_KEYUP : case WM_SYSKEYUP : ////////////////// { int keySymbol = 0; unsigned int modifierMask = 0; adaptKey(wParam, lParam, keySymbol, modifierMask); getEventQueue()->keyRelease(keySymbol, eventTime); getEventQueue()->getCurrentEventState()->setModKeyMask(modifierMask); } break; ///////////////// case WM_CLOSE : ///////////////// ::DestroyWindow(hwnd); break; ///////////////// case WM_DESTROY : ///////////////// destroyWindow(false); getEventQueue()->closeWindow(eventTime); ::PostQuitMessage(0); break; ///////////////// default : ///////////////// return ::DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } ////////////////////////////////////////////////////////////////////////////// // GraphicsContextWin32 implementation ////////////////////////////////////////////////////////////////////////////// GraphicsContextWin32::GraphicsContextWin32( osg::GraphicsContext::Traits* traits ) : _valid(false) { _traits = traits; } GraphicsContextWin32::~GraphicsContextWin32() { } bool GraphicsContextWin32::valid() const { return _valid; } bool GraphicsContextWin32::realizeImplementation() { osg::notify(osg::NOTICE) << "GraphicsContextWin32::realizeImplementation() not implemented." << std::endl; return false; } bool GraphicsContextWin32::isRealizedImplementation() const { osg::notify(osg::NOTICE) << "GraphicsContextWin32::isRealizedImplementation() not implemented." << std::endl; return false; } void GraphicsContextWin32::closeImplementation() { osg::notify(osg::NOTICE) << "GraphicsContextWin32::closeImplementation() not implemented." << std::endl; } bool GraphicsContextWin32::makeCurrentImplementation() { osg::notify(osg::NOTICE) << "GraphicsContextWin32::makeCurrentImplementation() not implemented." << std::endl; return false; } bool GraphicsContextWin32::makeContextCurrentImplementation( GraphicsContext* /*readContext*/ ) { osg::notify(osg::NOTICE) << "GraphicsContextWin32::makeContextCurrentImplementation(..) not implemented." << std::endl; return false; } bool GraphicsContextWin32::releaseContextImplementation() { osg::notify(osg::NOTICE) << "GraphicsContextWin32::releaseContextImplementation(..) not implemented." << std::endl; return false; } void GraphicsContextWin32::bindPBufferToTextureImplementation( GLenum /*buffer*/ ) { osg::notify(osg::NOTICE) << "GraphicsContextWin32::void bindPBufferToTextureImplementation(..) not implemented." << std::endl; } void GraphicsContextWin32::swapBuffersImplementation() { osg::notify(osg::NOTICE) << "GraphicsContextWin32:: swapBuffersImplementation() not implemented." << std::endl; } ////////////////////////////////////////////////////////////////////////////// // Class responsible for registering the Win32 Windowing System interface ////////////////////////////////////////////////////////////////////////////// struct RegisterWindowingSystemInterfaceProxy { RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(Win32WindowingSystem::getInterface()); } ~RegisterWindowingSystemInterfaceProxy() { osg::GraphicsContext::setWindowingSystemInterface(0); } }; static RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy; }; // namespace OsgViewer