Getting error wglMakeCurrent() has failed

Hello, I have a 3D application using OCC/V3d_View base on Qt 5.15...

The application run fine... but I have notice this error recently when I left my computer on with the application running all night, when I come back the next morning I got this error:

TKOpenGl.WinSystem | Type: Error | ID: 6 | Severity: High | Message:

  wglMakeCurrent() has failed. The handle is invalid.

TKOpenGl.WinSystem | Type: Error | ID: 6 | Severity: High |

  Message: wglMakeCurrent() has failed. The handle is invalid.

....

And then the V3d_View is all black and I can't see my model anymore.

Is this something that is known?  What can I activate to have more logging information so I can reproduce the problem and make a bug report if needed.

I use the following: Qt 5.15.12, OCC 7.7.0, Visual Studio 2019, Windows 11, NVidia RTX 3080

Here is the callstack I manage to grab:

1  OpenGl_Context::MakeCurrent           OpenGl_Context.cxx     726  0x7ffbf0fb8bd5 
2  OpenGl_Window::Activate               OpenGl_Window.cxx      755  0x7ffbf0f8e983 
3  OpenGl_Workspace::Activate            OpenGl_Workspace.cxx   158  0x7ffbf0f16061 
4  OpenGl_View::Redraw                   OpenGl_View.cxx        1641 0x7ffbf0f1dc12 
5  V3d_View::Redraw                      V3d_View.cxx           404  0x7ffbf0720df8 
6  AIS_ViewController::handleViewRedraw  AIS_ViewController.cxx 3158 0x7ffbf0903ff3 
7  prt::ViewController::handleViewRedraw prtviewcontroller.cpp  460  0x7ff660ffd901 
8  AIS_ViewController::HandleViewEvents  AIS_ViewController.cxx 3471 0x7ffbf08fd5e0 
9  AIS_ViewController::FlushViewEvents   AIS_ViewController.cxx 251  0x7ffbf08fd0dc 
10 prt::View3D::paintGL                  prtview3d.cpp          669  0x7ff660ff2260 
11 QOpenGLWidgetPrivate::invokeUserPaint qopenglwidget.cpp      895  0x7ffbda0dbf9f 
12 QOpenGLWidgetPrivate::render          qopenglwidget.cpp      916  0x7ffbda0dc062 
13 QOpenGLWidget::paintEvent             qopenglwidget.cpp      1328 0x7ffbda0da25a 
 

Any ideas?

Thanks,

Francois

gkv311 n's picture

I haven't heard about issues happening just because of long execution time. Consider checking the following scenarios:

  • Check system logs for possible graphic driver failures. OpenGL applications are not able to restore after system restarts GPU drivers.
  • Try locking / unlocking workstation with running application to see if it has any effect.
  • Try putting system into sleep / hibernation explicitly (if this is what might happened with your workstation at night).
  • Try collecting application logs with timestamps to see when first failure actually happened. Probably RAM / GPU memory statistics might be useful to detect GPU memory leaks.
  • If your system is a notebook with hybrid graphics, then try disabling auxiliary GPU to see if it solves the issue (maybe driver forced every saving mode somehow?).

If that is not the case, then maybe Qt does something wrong and tricky (recreated window for some reason? or recreated OpenGL context?). Try logging Qt events / check its documentation if QOpenGLWidget has such exceptional cases that should be treated somehow.

Francois Lauzon's picture

Hello,
It's been quite some time now since I posted about this problem.
Still not sure why this is happening but I found a way to reproduce it a lot quicked, maybe this could help to have hints about why.
- I use the OcctQtViewer example that you made Kirill (https://github.com/gkv311/occt-samples-qopenglwidget)
- I have a setup with 2 monitors: 1 DELL S3422DWG (Main display) and 1 LG 24EN43
- similar setup to when I first reported this problem: Qt 5.15.16, OCC 7.8.0, Visual Studio 2022, Windows 11, NVidia RTX 3080

To reproduce, I launch the application on my main display, I close the monitor so the application will switch to the other monitor, the 3d view become black and the message "TKOpenGl.WinSystem | Type: Error | ID: 6 | Severity: High | Message: wglMakeCurrent() has failed. The handle is invalid." start to appear.

Any hints on how to solve this? Can you reproduce this behavior on your own machine?

Thanks,
François

Patrik Mueller's picture

Hello,

I had similar problems in former times with another OpenGL framework and multiple monitors. I've got the black view on the 2nd screen when hardware acceleration was not available. Just an idea...

Greets,

Patrik

Francois Lauzon's picture

Hello Patrick,
thanks for the hint.
However, I'm not sure it is related. Everything is working fine on my 3 monitors, I can switch the example between each monitor without any glitch. It is when I poweroff the main monitor that the error/black screen occurs.
I will need to investigate more.

gkv311 n's picture

Windows platform has a peculliar mechanism for loading OpenGL drivers. Initially it was said that 'the driver is loaded based on the monitor, on which window is located' (e.g. when you have two GPUs and two monitors connected independently - you may get two OpenGL drivers loaded at once). Nowadays, Windows doesn't follow this logic - only one OpenGL driver is expected to be active at the moment (even in case of multi-GPU), but apparently there are still some logic behind window location.

I have seen the problem first time in multi-monitor configuration with ATi drivers many years ago - OpenGL context creation failed suddently when window was created on second monitor... And then I've tried to put some workarounds for this misbehavior (by attempt to create window on first monitor and then moving it to the second monitor).

I've also experienced some random crashes with Qt5 (QtQuick) apllication moved dynamically between monitors (haven't found workarounds, as I don't actually understand the cause - other OpenGL applications don't crash in the same scenario). I guess that there might be some bugs in Qt, or triggers some bugs in Windows or in OpenGL drivers...

Francois Lauzon's picture

Thanks for the answer Kirill.

I have only 1 NVIDIA card setup.
What I know is that CAD Assistant is working fine (must be using a different approach I guess, or must be doing something other than the sample you posted).
Also, the Qt sample that come with OCCT3D don't have this glitch, it is using QWidget instead of QOpenGLWidget. I don't remember what exactly but using QWidget was causing other issues for us.

I will need to investigate more because this is becoming an issue on multiple platform (gather more details about each setup).

Thanks,
Francois

gkv311 n's picture

Practically speaking, I was unable to apply workaround in Qt environment, because it has its internal workflow for creating OpenGL context and weird logic for window positioning... Just sharing my ideas - don't have a working solution, nor even sure what could be a reason, sorry ).

gkv311 n's picture

I know is that CAD Assistant is working fine ...

CAD Assistant relies on QtQuick, which has different routines for initializing OpenGL context than QOpenGLWidget. In addition, sample based on QWidget relies on OpenGL initialization implemented in OCCT rather than in Qt - hence it is less-dependant on whatever is implemented in Qt for OpenGL and doesn't suffer from integration issues...

I wanted to extend sample to demonstrate all 3 approaches, but have not found time for that.

Francois Lauzon's picture

I might try to make it work with QWidget instead and see what was the other issues I encountered.
If I find a working solution I'll post the results.

Thanks,
Francois

Francois Lauzon's picture

SOLVED

Ok, it's been a while but I have found a solution to the issue I was having. I did some test with a QWidget instead of QOpenGLWidget, but I had some issues when I was trying to put other widgets (pushbutton, ...) over the 3d view, I wasn't able to have a transparent background for those widgets. That is why I switched to the QOpenGLWidget in the first place.

What is happening with the QOpenGLWidget/OCC integration when a monitor is close is that a new Aspect_Window needs to be created and assign to the V3d_View.

To be more specific to my case, I simply use the QScreen::destroyed() signal (this means a screen was deleted, ie, a display monitor was close for example) and do the following when it is happening:


// same previous gl context and 3d view
opencascade::handle gl_context=...;
opencascade::handle view=...;

// create a new window with 
Handle(Aspect_Window) theWindow=new Aspect_Window;
#ifdef Q_OS_WIN
    HDC   wgl_dev_ctx = wglGetCurrentDC();
    HWND  wgl_win    = WindowFromDC (wgl_dev_ctx);
    Aspect_Drawable native_win = (Aspect_Drawable )wgl_win;
#else
    Aspect_Drawable native_win= (Aspect_Drawable )winId();
#endif
    window->SetNativeHandle(native_win);

view->SetWindow (window, gl_context);

This is now working fine, I only got the following OpenGL warning: TKOpenGl.OpenGL | Type: Error | ID: 1280 | Severity: High | Message: GL_INVALID_ENUM error generated. does not specify a valid attachment. This error occured when I do a view->SetWindow(); I trace back this error to OpenGL_Context line 1514:


      arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, aDefWinBuffer, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &aWinColorEncoding);

My knowledge in OpenGL is limited so I don't why at application startup there is no error but when I recreate the window I got this error.

But other than that it seems to be working fine.

gkv311 n's picture

Interesting... I'm curious what Qt actually does in this scenario and what the trick with QScreen::destroyed() signal handling changes...

Maybe Qt destroys HWND window and creates new one by reuses OpenGL context (otherwise, the trick wouldn't work and OCCT viewer would crash)? Could you try comparing Aspect_Window::NativeHandle() values for old/new window (and probably OpenGL context pointers) in QScreen::destroyed()?

Francois Lauzon's picture

First, I use Qt 5.15.16 and OCC 7.8.

QOpenGLContext is keeping track of when the QScreen linked with the gl context is destroyed (I supposed that's what is happening when a monitor is close).
Have a look at QOpenGLContext::setScreen() source code and the related QOpenGLContextPrivate::_q_screenDestroyed() slot (see qopenglcontext.cpp line 494).

The HWND is changing... I have update your occt-qopenglwidget-sample Kirill (see attached files) that will show what was changed to make it work (except for the OpenGl warning I mentionned earlier).

gkv311 n's picture

Francois, thanks for investigation.

I've been able to reproduce the crash by closing notebook lid with attached external monitor on Windows. Don't think that Qt does smart things in this scenario - other OpenGL applications work just fine without doing anything with HWND nor existing OpenGL context in the same scenario.

Anyway, I've pushed another hack to OcctQtViewer.cpp in occt-samples-qopenglwidget that solved crash for me. Would be interesting to know if it will work in your usage scenario, if you'll have some time to check...

Francois Lauzon's picture

Hi Kirill,
thanks for looking into it.
I tested you're h8ack and it is working in my case to.
I might end up using your hack since it doesn't require to track down QScreen::destroyed().

Thanks,
Francois

gkv311 n's picture

Hello, Francois. Thanks for testing!