From 4c397244f66f7e16a56be8e5299c3a2a50a70dea Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 18:30:33 +0100 Subject: [PATCH 01/10] add method 'RemoveCurrent' for unsetting context --- include/pangolin/display/display_internal.h | 4 ++++ include/pangolin/display/window.h | 15 +++++++++++++++ src/python/pypangolin/window.cpp | 7 +++++++ 3 files changed, 26 insertions(+) diff --git a/include/pangolin/display/display_internal.h b/include/pangolin/display/display_internal.h index 2fde33f6e..a39dea56f 100644 --- a/include/pangolin/display/display_internal.h +++ b/include/pangolin/display/display_internal.h @@ -114,6 +114,10 @@ struct PANGOLIN_EXPORT PangolinGl : public WindowInterface pango_print_warn("MakeCurrent: Not available with non-pangolin window.\n"); } + virtual void RemoveCurrent() override { + pango_print_warn("RemoveCurrent: Not available with non-pangolin window.\n"); + } + virtual void Move(int /*x*/, int /*y*/) override { pango_print_warn("Move: Not available with non-pangolin window.\n"); } diff --git a/include/pangolin/display/window.h b/include/pangolin/display/window.h index 7467e8f16..7e2dd598e 100644 --- a/include/pangolin/display/window.h +++ b/include/pangolin/display/window.h @@ -45,10 +45,25 @@ class WindowInterface virtual ~WindowInterface() {} virtual void ToggleFullscreen() = 0; + virtual void Move(int x, int y) = 0; + virtual void Resize(unsigned int w, unsigned int h) = 0; + + /** + * @brief MakeCurrent set the current context + * to be called in a thread before accessing OpenGL + */ virtual void MakeCurrent() = 0; + + /** + * @brief RemoveCurrent remove the current context + * to be called at the end of a thread + */ + virtual void RemoveCurrent() = 0; + virtual void ProcessEvents() = 0; + virtual void SwapBuffers() = 0; }; diff --git a/src/python/pypangolin/window.cpp b/src/python/pypangolin/window.cpp index 32dd7595b..9c87dcece 100644 --- a/src/python/pypangolin/window.cpp +++ b/src/python/pypangolin/window.cpp @@ -67,6 +67,13 @@ namespace py_pangolin { MakeCurrent); } + void RemoveCurrent() override { + PYBIND11_OVERLOAD_PURE( + void, + pangolin::WindowInterface, + RemoveCurrent); + } + void ProcessEvents() override { PYBIND11_OVERLOAD_PURE( void, From 3b7e332c7d181b74ff960e01c42b88e9f2b58135 Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 18:31:03 +0100 Subject: [PATCH 02/10] recursive mutex for locking context --- src/display/display.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/display/display.cpp b/src/display/display.cpp index 7ad9f094e..fb2646c29 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -74,7 +74,7 @@ typedef std::map > ContextMap; // Map of active contexts ContextMap contexts; -std::mutex contexts_mutex; +std::recursive_mutex contexts_mutex; bool one_time_window_frameworks_init = false; // Context active for current thread @@ -116,7 +116,7 @@ PangolinGl *FindContext(const std::string& name) WindowInterface& CreateWindowAndBind(std::string window_title, int w, int h, const Params& params) { - std::unique_lock l(contexts_mutex); + std::unique_lock l(contexts_mutex); if(!one_time_window_frameworks_init) { one_time_window_frameworks_init = LoadBuiltInWindowFrameworks(); @@ -223,7 +223,7 @@ void DestroyWindow(const std::string& name) WindowInterface& BindToContext(std::string name) { - std::unique_lock l(contexts_mutex); + std::unique_lock l(contexts_mutex); // N.B. context is modified prior to invoking MakeCurrent so that // state management callbacks (such as Resize()) can be correctly From d0e53669d338aad05f8b4fceb98efa474fe8b6bc Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 18:31:25 +0100 Subject: [PATCH 03/10] clear whitespace --- src/display/display.cpp | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/display/display.cpp b/src/display/display.cpp index fb2646c29..287f01bc7 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -321,7 +321,7 @@ void PostRender() context->screen_capture.pop(); SaveFramebuffer(fv.first, fv.second); } - + #ifdef BUILD_PANGOLIN_VIDEO if(context->recorder.IsOpen()) { SaveFramebuffer(context->recorder, context->record_view->GetBounds() ); @@ -408,7 +408,7 @@ void SaveFramebuffer(std::string prefix, const Viewport& v) { PANGOLIN_UNUSED(prefix); PANGOLIN_UNUSED(v); - + #ifndef HAVE_GLES #ifdef HAVE_PNG @@ -419,14 +419,14 @@ void SaveFramebuffer(std::string prefix, const Viewport& v) glReadPixels(v.l, v.b, v.w, v.h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.ptr ); SaveImage(buffer, fmt, prefix + ".png", false); #endif // HAVE_PNG - + #endif // HAVE_GLES } #ifdef BUILD_PANGOLIN_VIDEO void SaveFramebuffer(VideoOutput& video, const Viewport& v) { -#ifndef HAVE_GLES +#ifndef HAVE_GLES const StreamInfo& si = video.Streams()[0]; if(video.Streams().size()==0 || (int)si.Width() != v.w || (int)si.Height() != v.h) { video.Close(); @@ -436,7 +436,7 @@ void SaveFramebuffer(VideoOutput& video, const Viewport& v) static basetime last_time = TimeNow(); const basetime time_now = TimeNow(); last_time = time_now; - + static std::vector img; img.resize(v.w*v.h*4); @@ -458,7 +458,7 @@ void Keyboard( unsigned char key, int x, int y) { // Force coords to match OpenGl Window Coords y = context->base.v.h - y; - + #ifdef HAVE_APPLE_OPENGL_FRAMEWORK // Switch backspace and delete for OSX! if(key== '\b') { @@ -472,7 +472,7 @@ void Keyboard( unsigned char key, int x, int y) // Check if global key hook exists const KeyhookMap::iterator hook = context->keypress_hooks.find(key); - + #ifdef HAVE_PYTHON // Console receives all input when it is open if( context->console_view && context->console_view->IsShown() ) { @@ -490,7 +490,7 @@ void KeyboardUp(unsigned char key, int x, int y) { // Force coords to match OpenGl Window Coords y = context->base.v.h - y; - + if(context->activeDisplay && context->activeDisplay->handler) { context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,false); @@ -512,28 +512,28 @@ void Mouse( int button_raw, int state, int x, int y) { // Force coords to match OpenGl Window Coords y = context->base.v.h - y; - + last_x = (float)x; last_y = (float)y; const MouseButton button = (MouseButton)(1 << (button_raw & 0xf) ); const bool pressed = (state == 0); - + context->had_input = context->is_double_buffered ? 2 : 1; - + const bool fresh_input = ( (context->mouse_state & 7) == 0); - + if( pressed ) { context->mouse_state |= (button&7); }else{ context->mouse_state &= ~(button&7); } - + #if defined(_WIN_) context->mouse_state &= 0x0000ffff; context->mouse_state |= (button_raw >> 4) << 16; #endif - + if(fresh_input) { context->base.handler->Mouse(context->base,button,x,y,pressed,context->mouse_state); }else if(context->activeDisplay && context->activeDisplay->handler) { @@ -545,12 +545,12 @@ void MouseMotion( int x, int y) { // Force coords to match OpenGl Window Coords y = context->base.v.h - y; - + last_x = (float)x; last_y = (float)y; - + context->had_input = context->is_double_buffered ? 2 : 1; - + if( context->activeDisplay) { if( context->activeDisplay->handler ) @@ -564,9 +564,9 @@ void PassiveMouseMotion(int x, int y) { // Force coords to match OpenGl Window Coords y = context->base.v.h - y; - + context->base.handler->PassiveMouseMotion(context->base,x,y,context->mouse_state); - + last_x = (float)x; last_y = (float)y; } @@ -595,9 +595,9 @@ void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, flo // Assume coords already match OpenGl Window Coords context->had_input = context->is_double_buffered ? 2 : 1; - + const bool fresh_input = (context->mouse_state == 0); - + if(fresh_input) { context->base.handler->Special(context->base,inType,x,y,p1,p2,p3,p4,context->mouse_state); }else if(context->activeDisplay && context->activeDisplay->handler) { @@ -633,15 +633,15 @@ void DrawTextureToViewport(GLuint texid) OpenGlRenderState::ApplyIdentity(); glBindTexture(GL_TEXTURE_2D, texid); glEnable(GL_TEXTURE_2D); - + GLfloat sq_vert[] = { -1,-1, 1,-1, 1, 1, -1, 1 }; glVertexPointer(2, GL_FLOAT, 0, sq_vert); - glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); GLfloat sq_tex[] = { 0,0, 1,0, 1,1, 0,1 }; glTexCoordPointer(2, GL_FLOAT, 0, sq_tex); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_VERTEX_ARRAY); From 3765f27d268bd8d2ddeff6a82694bcaf2bbe21bd Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 11:35:08 +0100 Subject: [PATCH 04/10] implement 'RemoveCurrent' for GLX --- include/pangolin/display/device/X11Window.h | 2 ++ src/display/device/display_x11.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/pangolin/display/device/X11Window.h b/include/pangolin/display/device/X11Window.h index 499acd926..c34c724b8 100644 --- a/include/pangolin/display/device/X11Window.h +++ b/include/pangolin/display/device/X11Window.h @@ -89,6 +89,8 @@ struct X11Window : public PangolinGl void MakeCurrent() override; + void RemoveCurrent() override; + void SwapBuffers() override; void ProcessEvents() override; diff --git a/src/display/device/display_x11.cpp b/src/display/device/display_x11.cpp index bd00fe984..4d3295244 100644 --- a/src/display/device/display_x11.cpp +++ b/src/display/device/display_x11.cpp @@ -321,6 +321,11 @@ void X11Window::MakeCurrent() MakeCurrent(glcontext ? glcontext->glcontext : global_gl_context.lock()->glcontext); } +void X11Window::RemoveCurrent() +{ + glXMakeCurrent(display->display, 0, nullptr); +} + void X11Window::ToggleFullscreen() { const Atom _NET_WM_STATE_FULLSCREEN = XInternAtom(display->display, "_NET_WM_STATE_FULLSCREEN", True); From fede4c56897d930f51abf48844bddabd2013fe67 Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 11:34:42 +0100 Subject: [PATCH 05/10] pangolin example with shared context in threads --- examples/CMakeLists.txt | 1 + examples/HelloPangolinThreads/CMakeLists.txt | 6 ++ examples/HelloPangolinThreads/main.cpp | 64 ++++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 examples/HelloPangolinThreads/CMakeLists.txt create mode 100644 examples/HelloPangolinThreads/main.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 1b81a8043..d720c8550 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,6 +1,7 @@ # All examples depend on Pangolin GUI if(BUILD_PANGOLIN_GUI) add_subdirectory(HelloPangolin) + add_subdirectory(HelloPangolinThreads) add_subdirectory(SimpleMultiDisplay) add_subdirectory(SimpleDisplayImage) add_subdirectory(SimpleScene) diff --git a/examples/HelloPangolinThreads/CMakeLists.txt b/examples/HelloPangolinThreads/CMakeLists.txt new file mode 100644 index 000000000..78f02a31f --- /dev/null +++ b/examples/HelloPangolinThreads/CMakeLists.txt @@ -0,0 +1,6 @@ +# Find Pangolin (https://github.com/stevenlovegrove/Pangolin) +find_package(Pangolin 0.5 REQUIRED) +include_directories(${Pangolin_INCLUDE_DIRS}) + +add_executable(HelloPangolinThreads main.cpp) +target_link_libraries(HelloPangolinThreads ${Pangolin_LIBRARIES}) diff --git a/examples/HelloPangolinThreads/main.cpp b/examples/HelloPangolinThreads/main.cpp new file mode 100644 index 000000000..04803322c --- /dev/null +++ b/examples/HelloPangolinThreads/main.cpp @@ -0,0 +1,64 @@ +#include +#include + +static const std::string window_name = "HelloPangolinThreads"; + +void setup() { + // create a window and bind its context to the main thread + pangolin::CreateWindowAndBind(window_name, 640, 480); + + // enable depth + glEnable(GL_DEPTH_TEST); + + // unset the current context from the main thread + pangolin::GetBoundWindow()->RemoveCurrent(); +} + +void run() { + // fetch the context and bind it to this thread + pangolin::BindToContext(window_name); + + // we manually need to restore the properties of the context + glEnable(GL_DEPTH_TEST); + + // Define Projection and initial ModelView matrix + pangolin::OpenGlRenderState s_cam( + pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100), + pangolin::ModelViewLookAt(-2,2,-2, 0,0,0, pangolin::AxisY) + ); + + // Create Interactive View in window + pangolin::Handler3D handler(s_cam); + pangolin::View& d_cam = pangolin::CreateDisplay() + .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f) + .SetHandler(&handler); + + while( !pangolin::ShouldQuit() ) + { + // Clear screen and activate view to render into + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + d_cam.Activate(s_cam); + + // Render OpenGL Cube + pangolin::glDrawColouredCube(); + + // Swap frames and Process Events + pangolin::FinishFrame(); + } + + // unset the current context from the main thread + pangolin::GetBoundWindow()->RemoveCurrent(); +} + +int main( int /*argc*/, char** /*argv*/ ) +{ + // create window and context in the main thread + setup(); + + // use the context in a separate rendering thread + std::thread render_loop; + render_loop = std::thread(run); + render_loop.join(); + + return 0; +} From af102cae8568c89e65005c3e4f4e69e193b5f72c Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 11:58:05 +0100 Subject: [PATCH 06/10] implement 'RemoveCurrent' for WGL --- include/pangolin/display/device/WinWindow.h | 2 ++ src/display/device/display_win.cpp | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/include/pangolin/display/device/WinWindow.h b/include/pangolin/display/device/WinWindow.h index f99206a97..35e85adcf 100644 --- a/include/pangolin/display/device/WinWindow.h +++ b/include/pangolin/display/device/WinWindow.h @@ -57,6 +57,8 @@ struct WinWindow : public PangolinGl void MakeCurrent() override; + void RemoveCurrent() override; + void SwapBuffers() override; void ProcessEvents() override; diff --git a/src/display/device/display_win.cpp b/src/display/device/display_win.cpp index 46d960a85..ae4393913 100644 --- a/src/display/device/display_win.cpp +++ b/src/display/device/display_win.cpp @@ -435,6 +435,11 @@ void WinWindow::MakeCurrent() Resize(rect.right - rect.left, rect.bottom - rect.top); } +void WinWindow::RemoveCurrent() +{ + wglMakeCurrent(NULL, NULL); +} + void WinWindow::SwapBuffers() { ::SwapBuffers(hDC); From c5c48f5457facc967397390e0390617aa666c2a3 Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 14:03:25 +0100 Subject: [PATCH 07/10] WGL error checking --- src/display/device/display_win.cpp | 174 +++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 32 deletions(-) diff --git a/src/display/device/display_win.cpp b/src/display/device/display_win.cpp index ae4393913..74a81f68a 100644 --- a/src/display/device/display_win.cpp +++ b/src/display/device/display_win.cpp @@ -34,6 +34,23 @@ #include #include +#define CheckWGLDieOnError() pangolin::_CheckWLDieOnError( __FILE__, __LINE__ ); +namespace pangolin { +inline void _CheckWLDieOnError( const char *sFile, const int nLine ) +{ + DWORD errorCode = GetLastError(); + if(errorCode!=0) { + LPVOID lpMsgBuf; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPTSTR) &lpMsgBuf, 0, NULL); + // MessageBox( NULL, (LPCTSTR)lpMsgBuf, ("Error "+std::to_string(errorCode)).c_str(), MB_OK | MB_ICONINFORMATION ); + pango_print_error("Error %i: %s", errorCode, (char *)lpMsgBuf); + pango_print_error("In: %s, line %d\n", sFile, nLine); + // exit(EXIT_FAILURE); + } +} +} + namespace pangolin { @@ -124,14 +141,14 @@ void WinWindow::SetupPixelFormat(HDC hDC) pixelFormat = ChoosePixelFormat(hDC, &pfd); if (pixelFormat == 0) { - MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", - MB_ICONERROR | MB_OK); + MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error", MB_ICONERROR | MB_OK); + CheckWGLDieOnError(); exit(1); } if (SetPixelFormat(hDC, pixelFormat, &pfd) != TRUE) { - MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", - MB_ICONERROR | MB_OK); + MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error", MB_ICONERROR | MB_OK); + CheckWGLDieOnError(); exit(1); } } @@ -139,11 +156,19 @@ void WinWindow::SetupPixelFormat(HDC hDC) void WinWindow::SetupPalette(HDC hDC) { int pixelFormat = GetPixelFormat(hDC); + if(!pixelFormat) { + std::cerr << "GetPixelFormat() failed" << std::endl; + CheckWGLDieOnError(); + } + PIXELFORMATDESCRIPTOR pfd; LOGPALETTE* pPal; int paletteSize; - DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); + if(!DescribePixelFormat(hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { + std::cerr << "DescribePixelFormat() failed" << std::endl; + CheckWGLDieOnError(); + } if (pfd.dwFlags & PFD_NEED_PALETTE) { paletteSize = 1 << pfd.cColorBits; @@ -152,8 +177,7 @@ void WinWindow::SetupPalette(HDC hDC) return; } - pPal = (LOGPALETTE*) - malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); + pPal = (LOGPALETTE*) malloc(sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY)); pPal->palVersion = 0x300; pPal->palNumEntries = paletteSize; @@ -182,6 +206,9 @@ void WinWindow::SetupPalette(HDC hDC) SelectPalette(hDC, hPalette, FALSE); RealizePalette(hDC); } + else { + std::cerr << "CreatePalette() failed" << std::endl; + } } WinWindow::WinWindow( @@ -189,6 +216,10 @@ WinWindow::WinWindow( ) : hWnd(0) { const HMODULE hCurrentInst = GetModuleHandle(0); + if(hCurrentInst==NULL) { + std::cerr << "GetModuleHandle() failed" << std::endl; + CheckWGLDieOnError(); + } RegisterThisClass(hCurrentInst); PangolinGl::windowed_size[0] = 0; @@ -199,6 +230,10 @@ WinWindow::WinWindow( WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, width, height, NULL, NULL, hCurrentInst, this); + if(thishwnd==NULL) { + std::cerr << "CreateWindow() failed" << std::endl; + CheckWGLDieOnError(); + } if( thishwnd != hWnd ) { throw std::runtime_error("Pangolin Window Creation Failed."); @@ -211,7 +246,10 @@ WinWindow::WinWindow( WinWindow::~WinWindow() { - DestroyWindow(hWnd); + if(!DestroyWindow(hWnd)) { + std::cerr << "DestroyWindow() failed" << std::endl; + CheckWGLDieOnError(); + } } void WinWindow::RegisterThisClass(HMODULE hCurrentInst) @@ -227,7 +265,10 @@ void WinWindow::RegisterThisClass(HMODULE hCurrentInst) wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = className; - RegisterClass(&wndClass); + if(!RegisterClass(&wndClass)) { + std::cerr << "RegisterClass() failed" << std::endl; + CheckWGLDieOnError(); + } } LRESULT APIENTRY @@ -259,16 +300,32 @@ LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam) case WM_CREATE: /* initialize OpenGL rendering */ hDC = GetDC(hWnd); + if(hDC==NULL) { + std::cerr << "WM_CREATE GetDC() failed" << std::endl; + } SetupPixelFormat(hDC); SetupPalette(hDC); hGLRC = wglCreateContext(hDC); - wglMakeCurrent(hDC, hGLRC); + if(!hGLRC) { + std::cerr << "WM_CREATE wglCreateContext() failed" << std::endl; + CheckWGLDieOnError(); + } + if(!wglMakeCurrent(hDC, hGLRC)) { + std::cerr << "WM_CREATE wglMakeCurrent() failed" << std::endl; + CheckWGLDieOnError(); + } return 0; case WM_DESTROY: /* finish OpenGL rendering */ if (hGLRC) { - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hGLRC); + if(!wglMakeCurrent(NULL, NULL)) { + std::cerr << "WM_DESTROY wglMakeCurrent() failed" << std::endl; + CheckWGLDieOnError(); + } + if(!wglDeleteContext(hGLRC)) { + std::cerr << "WM_DESTROY wglDeleteContext() failed" << std::endl; + CheckWGLDieOnError(); + } } if (hPalette) { DeleteObject(hPalette); @@ -285,9 +342,15 @@ LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam) case WM_PALETTECHANGED: /* realize palette if this is *not* the current window */ if (hGLRC && hPalette && (HWND)wParam != hWnd) { - UnrealizeObject(hPalette); - SelectPalette(hDC, hPalette, FALSE); - RealizePalette(hDC); + if(!UnrealizeObject(hPalette)) { + std::cerr << "WM_PALETTECHANGED UnrealizeObject() failed" << std::endl; + } + if(!SelectPalette(hDC, hPalette, FALSE)) { + std::cerr << "WM_PALETTECHANGED SelectPalette() failed" << std::endl; + } + if(RealizePalette(hDC)==GDI_ERROR) { + std::cerr << "WM_PALETTECHANGED RealizePalette() failed" << std::endl; + } //redraw(); break; } @@ -295,9 +358,15 @@ LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam) case WM_QUERYNEWPALETTE: /* realize palette if this is the current window */ if (hGLRC && hPalette) { - UnrealizeObject(hPalette); - SelectPalette(hDC, hPalette, FALSE); - RealizePalette(hDC); + if(!UnrealizeObject(hPalette)) { + std::cerr << "WM_QUERYNEWPALETTE UnrealizeObject() failed" << std::endl; + } + if(!SelectPalette(hDC, hPalette, FALSE)) { + std::cerr << "WM_QUERYNEWPALETTE SelectPalette() failed" << std::endl; + } + if(RealizePalette(hDC)==GDI_ERROR) { + std::cerr << "WM_QUERYNEWPALETTE RealizePalette() failed" << std::endl; + } //redraw(); return TRUE; } @@ -368,11 +437,25 @@ LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam) void WinWindow::StartFullScreen() { LONG dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE) & ~(WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE); + if(dwExStyle==0) { + std::cerr << "GetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } LONG dwStyle = GetWindowLong(hWnd, GWL_STYLE) & ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZE | WS_MAXIMIZE | WS_SYSMENU); + if(dwStyle==0) { + std::cerr << "GetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } - SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - SetWindowLong(hWnd, GWL_STYLE, dwStyle); + if(!SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle)) { + std::cerr << "SetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } + if(!SetWindowLong(hWnd, GWL_STYLE, dwStyle)) { + std::cerr << "SetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } GLint prev[2]; std::memcpy(prev, context->windowed_size, sizeof(prev)); @@ -381,21 +464,34 @@ void WinWindow::StartFullScreen() { } void WinWindow::StopFullScreen() { - ChangeDisplaySettings(NULL, 0); ShowCursor(TRUE); LONG dwExStyle = GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; LONG dwStyle = GetWindowLong(hWnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW; - SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle); - SetWindowLong(hWnd, GWL_STYLE, dwStyle); + if(dwExStyle==0) { + std::cerr << "GetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } + if(dwStyle==0) { + std::cerr << "GetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } + + if(!SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle)) { + std::cerr << "SetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } + if(!SetWindowLong(hWnd, GWL_STYLE, dwStyle)) { + std::cerr << "SetWindowLong() failed" << std::endl; + CheckWGLDieOnError(); + } - SetWindowPos(hWnd, - HWND_TOP, - 0, 0, - context->windowed_size[0], context->windowed_size[1], - SWP_FRAMECHANGED); + if(!SetWindowPos(hWnd, HWND_TOP, 0, 0, context->windowed_size[0], context->windowed_size[1], SWP_FRAMECHANGED)) { + std::cerr << "SetWindowPos() failed" << std::endl; + CheckWGLDieOnError(); + } } void WinWindow::ToggleFullscreen() @@ -413,6 +509,7 @@ void WinWindow::Move(int x, int y) { if( !SetWindowPos(hWnd, 0, x, y, 0, 0, SWP_NOSIZE) ) { std::cerr << "WinWindow::Move failed" << std::endl; + CheckWGLDieOnError(); } } @@ -420,29 +517,42 @@ void WinWindow::Resize(unsigned int w, unsigned int h) { if( !SetWindowPos(hWnd, 0, 0, 0, w, h, SWP_NOMOVE) ) { std::cerr << "WinWindow::Resize failed" << std::endl; + CheckWGLDieOnError(); } } void WinWindow::MakeCurrent() { - wglMakeCurrent(hDC, hGLRC); + if(wglMakeCurrent(hDC, hGLRC)==FALSE) { + std::cerr << "wglMakeCurrent() failed" << std::endl; + CheckWGLDieOnError(); + } // Setup threadlocal context as this context = this; RECT rect; - GetWindowRect(hWnd, &rect); + if(!GetWindowRect(hWnd, &rect)) { + std::cerr << "GetWindowRect() failed" << std::endl; + CheckWGLDieOnError(); + } Resize(rect.right - rect.left, rect.bottom - rect.top); } void WinWindow::RemoveCurrent() { - wglMakeCurrent(NULL, NULL); + if(wglMakeCurrent(NULL, NULL)==0) { + std::cerr << "wglMakeCurrent() failed" << std::endl; + CheckWGLDieOnError(); + } } void WinWindow::SwapBuffers() { - ::SwapBuffers(hDC); + if(!::SwapBuffers(hDC)) { + std::cerr << "SwapBuffers() failed" << std::endl; + CheckWGLDieOnError(); + } } void WinWindow::ProcessEvents() From e445f08da550596884d544254c9f5ec1d3367916 Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 14:30:30 +0100 Subject: [PATCH 08/10] implement 'RemoveCurrent' for CGL --- include/pangolin/display/device/OsxWindow.h | 2 ++ src/display/device/display_osx.mm | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/pangolin/display/device/OsxWindow.h b/include/pangolin/display/device/OsxWindow.h index 01c14db3c..4d1be5df7 100644 --- a/include/pangolin/display/device/OsxWindow.h +++ b/include/pangolin/display/device/OsxWindow.h @@ -54,6 +54,8 @@ struct OsxWindow : public PangolinGl void MakeCurrent() override; + void RemoveCurrent() override; + void SwapBuffers() override; void ProcessEvents() override; diff --git a/src/display/device/display_osx.mm b/src/display/device/display_osx.mm index e879d4043..3785c6ef0 100644 --- a/src/display/device/display_osx.mm +++ b/src/display/device/display_osx.mm @@ -202,6 +202,12 @@ inline void FixOsxFocus() void OsxWindow::MakeCurrent() { [[view openGLContext] makeCurrentContext]; + context = this; +} + +void OsxWindow::RemoveCurrent() +{ + [NSOpenGLContext clearCurrentContext]; } void OsxWindow::SwapBuffers() From f343fa521b2c0840b0d32be336e723912271aa1b Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Mon, 6 Aug 2018 14:32:19 +0100 Subject: [PATCH 09/10] implement WaylandWindow::RemoveCurrent() --- src/display/device/display_wayland.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/display/device/display_wayland.cpp b/src/display/device/display_wayland.cpp index fa3ad4703..3f8797d0e 100755 --- a/src/display/device/display_wayland.cpp +++ b/src/display/device/display_wayland.cpp @@ -392,6 +392,8 @@ struct WaylandWindow : public PangolinGl void MakeCurrent() override; + void RemoveCurrent() override; + void SwapBuffers() override; void ProcessEvents() override; @@ -836,6 +838,10 @@ void WaylandWindow::MakeCurrent() { context = this; } +void WaylandWindow::RemoveCurrent() { + eglMakeCurrent(display->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + void WaylandWindow::ToggleFullscreen() { is_fullscreen = !is_fullscreen; // state for Pangolin display->is_fullscreen = is_fullscreen; // state for Wayland From fef28657b35cb84fca3008343ce5deae2f5ec151 Mon Sep 17 00:00:00 2001 From: Christian Rauch Date: Wed, 15 Aug 2018 15:26:58 +0100 Subject: [PATCH 10/10] do not make newly created non-window contexts current --- src/display/display.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/display/display.cpp b/src/display/display.cpp index 287f01bc7..ad772400c 100644 --- a/src/display/display.cpp +++ b/src/display/display.cpp @@ -233,7 +233,6 @@ WindowInterface& BindToContext(std::string name) { std::shared_ptr newcontext(new PangolinGl()); RegisterNewContext(name, newcontext); - newcontext->MakeCurrent(); return *(newcontext.get()); }else{ context_to_bind->MakeCurrent();