0002-windows-Improve-error-handling-with-EGL.patch 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. From 867fc30c7c9be51b4b3813d2cc558b5a9df0256d Mon Sep 17 00:00:00 2001
  2. From: Laszlo Agocs <laszlo.agocs@digia.com>
  3. Date: Wed, 23 Sep 2015 14:38:48 +0200
  4. Subject: [PATCH] windows: Improve error handling with EGL
  5. When disabling the graphics adapter, things start failing
  6. with context lost and then bad_alloc and bad_access failures
  7. when creating contexts/window surfaces.
  8. Swap buffers now handles context loss. This makes it possible
  9. for Qt Quick to act when the graphics adapter goes away.
  10. Similarly, the window surface creation failure EGL_BAD_ACCESS
  11. is treated the same way as context loss.
  12. Note that this will not really help the main issue, because
  13. rendering is not possible without a GPU (reinit attempts will
  14. fail either at context creation or window surface creation),
  15. but proper logging and context loss reporting improves the
  16. situation somewhat.
  17. Also unify and prettyify the warning and debug prints.
  18. This makes it easier to understand what is going on.
  19. Change-Id: Iec3a9b54f1134e78e87eefcf938525283ec9412a
  20. Task-number: QTBUG-48095
  21. Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
  22. ---
  23. .../platforms/windows/qwindowseglcontext.cpp | 43 ++++++++++++++++------
  24. 1 file changed, 31 insertions(+), 12 deletions(-)
  25. diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
  26. index 06c9985..e4ec3f3 100644
  27. --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
  28. +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
  29. @@ -350,16 +350,16 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
  30. {
  31. const HDC dc = QWindowsContext::instance()->displayContext();
  32. if (!dc){
  33. - qWarning("%s: No Display", Q_FUNC_INFO);
  34. + qWarning("%s: No Display", __FUNCTION__);
  35. return 0;
  36. }
  37. if (!libEGL.init()) {
  38. - qWarning("%s: Failed to load and resolve libEGL functions", Q_FUNC_INFO);
  39. + qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
  40. return 0;
  41. }
  42. if (!libGLESv2.init()) {
  43. - qWarning("%s: Failed to load and resolve libGLESv2 functions", Q_FUNC_INFO);
  44. + qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
  45. return 0;
  46. }
  47. @@ -396,15 +396,15 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
  48. if (display == EGL_NO_DISPLAY)
  49. display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc);
  50. if (!display) {
  51. - qWarning("%s: Could not obtain EGL display", Q_FUNC_INFO);
  52. + qWarning("%s: Could not obtain EGL display", __FUNCTION__);
  53. return 0;
  54. }
  55. if (!major && !libEGL.eglInitialize(display, &major, &minor)) {
  56. int err = libEGL.eglGetError();
  57. - qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err);
  58. + qWarning("%s: Could not initialize EGL display: error 0x%x", __FUNCTION__, err);
  59. if (err == 0x3001)
  60. - qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", Q_FUNC_INFO);
  61. + qWarning("%s: When using ANGLE, check if d3dcompiler_4x.dll is available", __FUNCTION__);
  62. return 0;
  63. }
  64. @@ -430,7 +430,7 @@ void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *na
  65. (EGLNativeWindowType) nativeWindow, 0);
  66. if (surface == EGL_NO_SURFACE) {
  67. *err = libEGL.eglGetError();
  68. - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
  69. + qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err);
  70. }
  71. return surface;
  72. @@ -533,7 +533,12 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext,
  73. }
  74. if (m_eglContext == EGL_NO_CONTEXT) {
  75. - qWarning("QWindowsEGLContext: eglError: %x, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
  76. + int err = QWindowsEGLStaticContext::libEGL.eglGetError();
  77. + qWarning("QWindowsEGLContext: Failed to create context, eglError: %x, this: %p", err, this);
  78. + // ANGLE gives bad alloc when it fails to reset a previously lost D3D device.
  79. + // A common cause for this is disabling the graphics adapter used by the app.
  80. + if (err == EGL_BAD_ALLOC)
  81. + qWarning("QWindowsEGLContext: Graphics device lost. (Did the adapter get disabled?)");
  82. return;
  83. }
  84. @@ -594,6 +599,12 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
  85. if (err == EGL_CONTEXT_LOST) {
  86. m_eglContext = EGL_NO_CONTEXT;
  87. qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
  88. + } else if (err == EGL_BAD_ACCESS) {
  89. + // With ANGLE this means no (D3D) device and can happen when disabling/changing graphics adapters.
  90. + qCDebug(lcQpaGl) << "Bad access (missing device?) in createWindowSurface() for context" << this;
  91. + // Simulate context loss as the context is useless.
  92. + QWindowsEGLStaticContext::libEGL.eglDestroyContext(m_eglDisplay, m_eglContext);
  93. + m_eglContext = EGL_NO_CONTEXT;
  94. }
  95. return false;
  96. }
  97. @@ -623,7 +634,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
  98. // Drop the surface. Will recreate on the next makeCurrent.
  99. window->invalidateSurface();
  100. } else {
  101. - qWarning("QWindowsEGLContext::makeCurrent: eglError: %x, this: %p \n", err, this);
  102. + qWarning("%s: Failed to make surface current. eglError: %x, this: %p", __FUNCTION__, err, this);
  103. }
  104. }
  105. @@ -635,7 +646,8 @@ void QWindowsEGLContext::doneCurrent()
  106. QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
  107. bool ok = QWindowsEGLStaticContext::libEGL.eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  108. if (!ok)
  109. - qWarning("QWindowsEGLContext::doneCurrent: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
  110. + qWarning("%s: Failed to make no context/surface current. eglError: %d, this: %p", __FUNCTION__,
  111. + QWindowsEGLStaticContext::libEGL.eglGetError(), this);
  112. }
  113. void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
  114. @@ -653,8 +665,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
  115. }
  116. bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
  117. - if (!ok)
  118. - qWarning("QWindowsEGLContext::swapBuffers: eglError: %d, this: %p \n", QWindowsEGLStaticContext::libEGL.eglGetError(), this);
  119. + if (!ok) {
  120. + err = QWindowsEGLStaticContext::libEGL.eglGetError();
  121. + if (err == EGL_CONTEXT_LOST) {
  122. + m_eglContext = EGL_NO_CONTEXT;
  123. + qCDebug(lcQpaGl) << "Got EGL context lost in eglSwapBuffers()";
  124. + } else {
  125. + qWarning("%s: Failed to swap buffers. eglError: %d, this: %p", __FUNCTION__, err, this);
  126. + }
  127. + }
  128. }
  129. QFunctionPointer QWindowsEGLContext::getProcAddress(const QByteArray &procName)
  130. --
  131. 2.5.1