123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- From 867fc30c7c9be51b4b3813d2cc558b5a9df0256d Mon Sep 17 00:00:00 2001
- From: Laszlo Agocs <laszlo.agocs@digia.com>
- Date: Wed, 23 Sep 2015 14:38:48 +0200
- Subject: [PATCH] windows: Improve error handling with EGL
- When disabling the graphics adapter, things start failing
- with context lost and then bad_alloc and bad_access failures
- when creating contexts/window surfaces.
- Swap buffers now handles context loss. This makes it possible
- for Qt Quick to act when the graphics adapter goes away.
- Similarly, the window surface creation failure EGL_BAD_ACCESS
- is treated the same way as context loss.
- Note that this will not really help the main issue, because
- rendering is not possible without a GPU (reinit attempts will
- fail either at context creation or window surface creation),
- but proper logging and context loss reporting improves the
- situation somewhat.
- Also unify and prettyify the warning and debug prints.
- This makes it easier to understand what is going on.
- Change-Id: Iec3a9b54f1134e78e87eefcf938525283ec9412a
- Task-number: QTBUG-48095
- Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
- ---
- .../platforms/windows/qwindowseglcontext.cpp | 43 ++++++++++++++++------
- 1 file changed, 31 insertions(+), 12 deletions(-)
- diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
- index 06c9985..e4ec3f3 100644
- --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
- +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
- @@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
- {
- const HDC dc = QWindowsContext::instance()->displayContext();
- if (!dc){
- - qWarning("%s: No Display", Q_FUNC_INFO);
- + qWarning("%s: No Display", __FUNCTION__);
- return 0;
- }
-
- if (!libEGL.init()) {
- - qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
- + qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
- return 0;
- }
- if (!libGLESv2.init()) {
- - qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
- + qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
- return 0;
- }
-
- @@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
- if (display == EGL_NO_DISPLAY)
- display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
- if (!display) {
- - qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
- + qWarning("%s: Could not obtain EGL display", __FUNCTION__);
- return 0;
- }
-
- if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
- int err = libEGL.eglGetError();
- - qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
- + qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
- if (err == 0x3001)
- - qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
- + qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
- return 0;
- }
-
- @@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na
- (EGLNativeWindowType) nativeWindow, 0);
- if (surface == EGL_NO_SURFACE) {
- *err = libEGL.eglGetError();
- - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
- + qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
- }
-
- return surface;
- @@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
- }
-
- if (m_eglContext == EGL_NO_CONTEXT) {
- - qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
- + int err = QWindowsEGLStaticContext::libEGL.eglGetError();
- + qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
- + // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
- + // A common cause for this is disabling the graphics adapter used by the app.
- + if (err == EGL_BAD_ALLOC)
- + qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
- return;
- }
-
- @@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
- if (err == EGL_CONTEXT_LOST) {
- m_eglContext = EGL_NO_CONTEXT;
- qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
- + } else if (err == EGL_BAD_ACCESS) {
- + // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
- + qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
- + // Simulate context loss as the context is useless.
- + QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
- + m_eglContext = EGL_NO_CONTEXT;
- }
- return false;
- }
- @@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
- // Drop the surface. Will recreate on the next makeCurrent.
- window->invalidateSurface();
- } else {
- - qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this);
- + qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
- }
- }
-
- @@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent()
- QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- if (!ok)
- - qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
- + qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
- + QWindowsEGLStaticContext::libEGL.eglGetError(), this);
- }
-
- void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
- @@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
- }
-
- bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
- - if (!ok)
- - qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
- + if (!ok) {
- + err = QWindowsEGLStaticContext::libEGL.eglGetError();
- + if (err == EGL_CONTEXT_LOST) {
- + m_eglContext = EGL_NO_CONTEXT;
- + qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
- + } else {
- + qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
- + }
- + }
- }
-
- QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
- --
- 2.5.1
|