From 97da4519ba94164d6c6ddad6ffa9a16153d74a55 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 4 Jan 2021 10:27:11 +0100 Subject: [PATCH] Add a dedicated QWindow surface type for D3D MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even though there is no D3D-specific logic in the windows platform plugin, meaning a QWindow with either OpenGLSurface or VulkanSurface (or anything really) is DXGI/D3D-compatible, it now looks like it is beneficial, and more future proof, if there is a dedicated surface type. As the linked report shows, there are OpenGL-specific workarounds accumulated in the platform plugin, while not being clear if these are relevant to non-OpenGL content, or if they are relevant at all still. (and some of these can be difficult/impossible to retest and verify in practice) When D3D-based windows use the same surface type, all these are active for those windows as well, while Vulkan-based windows have their own type and so some of these old workarounds are not active for those. To reduce confusion, having a dedicated surface type for D3D as well allows the logic to skip the old OpenGL workarounds, giving us (and users) a more clear overall behavior when it comes to OpenGL vs. Vulkan vs. D3D. The change is compatible with any existing code in other modules because any code that uses OpenGLSurface for D3D will continue to work, using the new type can be introduced incrementally. Task-number: QTBUG-89715 Change-Id: Ieba86a580bf5a3636730952184dc3a3ab7669b26 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qsurface.cpp | 4 ++- src/gui/kernel/qsurface.h | 3 +- .../platforms/windows/qwindowswindow.cpp | 36 +++++++++++-------- .../platforms/windows/qwindowswindow.h | 4 +-- .../hellominimalcrossgfxtriangle/window.cpp | 2 +- tests/manual/rhi/multiwindow/multiwindow.cpp | 4 +-- .../rhi/multiwindow_threaded/window.cpp | 4 +-- tests/manual/rhi/shared/examplefw.h | 2 +- 8 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp index 85c576b21cd..5a293e42504 100644 --- a/src/gui/kernel/qsurface.cpp +++ b/src/gui/kernel/qsurface.cpp @@ -85,7 +85,9 @@ QT_BEGIN_NAMESPACE \value MetalSurface The surface is a Metal compatible surface and can be used in conjunction with Apple's Metal graphics API. This surface type is supported on macOS only. - + \value Direct3DSurface The surface is a Direct 3D 11 and 12 compatible + surface and can be used in conjunction with the DXGI and Direct3D APIs. This + surface type is supported on Windows only. */ diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h index 521593ea5c7..4ba1d4b5891 100644 --- a/src/gui/kernel/qsurface.h +++ b/src/gui/kernel/qsurface.h @@ -69,7 +69,8 @@ public: RasterGLSurface, OpenVGSurface, VulkanSurface, - MetalSurface + MetalSurface, + Direct3DSurface }; Q_ENUM(SurfaceType) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 5987324ac11..7528bf41552 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -351,6 +351,8 @@ static inline bool windowIsAccelerated(const QWindow *w) return qt_window_private(const_cast(w))->compositing; case QSurface::VulkanSurface: return true; + case QSurface::Direct3DSurface: + return true; default: return false; } @@ -1365,14 +1367,12 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) const Qt::WindowType type = aWindow->type(); if (type == Qt::Desktop) return; // No further handling for Qt::Desktop -#ifndef QT_NO_OPENGL - if (aWindow->surfaceType() == QWindow::OpenGLSurface) { - if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) - setFlag(OpenGLSurface); - else - setFlag(OpenGL_ES2); - } -#endif // QT_NO_OPENGL + if (aWindow->surfaceType() == QWindow::Direct3DSurface) + setFlag(Direct3DSurface); +#if QT_CONFIG(opengl) + if (aWindow->surfaceType() == QWindow::OpenGLSurface) + setFlag(OpenGLSurface); +#endif #if QT_CONFIG(vulkan) if (aWindow->surfaceType() == QSurface::VulkanSurface) setFlag(VulkanSurface); @@ -1831,8 +1831,11 @@ void QWindowsWindow::handleHidden() void QWindowsWindow::handleCompositionSettingsChanged() { const QWindow *w = window(); - if ((w->surfaceType() == QWindow::OpenGLSurface || w->surfaceType() == QWindow::VulkanSurface) - && w->format().hasAlpha()) { + if ((w->surfaceType() == QWindow::OpenGLSurface + || w->surfaceType() == QWindow::VulkanSurface + || w->surfaceType() == QWindow::Direct3DSurface) + && w->format().hasAlpha()) + { applyBlurBehindWindow(handle()); } } @@ -2008,9 +2011,10 @@ void QWindowsWindow::handleGeometryChange() return; // QGuiApplication will send resize when screen actually changes } QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry); - // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive - // expose events when shrinking, synthesize. - if (!testFlag(OpenGL_ES2) && isExposed() + // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE + // which we no longer support in Qt 6) do not receive expose + // events when shrinking, synthesize. + if (isExposed() && m_data.geometry.size() != previousGeometry.size() // Exclude plain move // One dimension grew -> Windows will send expose, no need to synthesize. && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { @@ -2139,7 +2143,9 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message, // Observed painting problems with Aero style disabled (QTBUG-7865). if (Q_UNLIKELY(!dwmIsCompositionEnabled()) - && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface))) + && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) + || testFlag(VulkanSurface) + || testFlag(Direct3DSurface))) { SelectClipRgn(ps.hdc, nullptr); } @@ -2523,7 +2529,7 @@ void QWindowsWindow::setOpacity(qreal level) m_opacity = level; if (m_data.hwnd) setWindowOpacity(m_data.hwnd, m_data.flags, - window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface), + window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface) || testFlag(Direct3DSurface), level); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 1f1af82da22..b0f58b09a95 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -219,7 +219,6 @@ public: WithinSetParent = 0x2, WithinSetGeometry = 0x8, OpenGLSurface = 0x10, - OpenGL_ES2 = 0x20, OpenGLDoubleBuffered = 0x40, OpenGlPixelFormatInitialized = 0x80, BlockedByModal = 0x100, @@ -239,7 +238,8 @@ public: WithinDpiChanged = 0x400000, VulkanSurface = 0x800000, ResizeMoveActive = 0x1000000, - DisableNonClientScaling = 0x2000000 + DisableNonClientScaling = 0x2000000, + Direct3DSurface = 0x4000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); diff --git a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp index 0395ffd8bbd..edcb81b4fe0 100644 --- a/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp +++ b/tests/manual/rhi/hellominimalcrossgfxtriangle/window.cpp @@ -65,7 +65,7 @@ Window::Window(QRhi::Implementation graphicsApi) setSurfaceType(VulkanSurface); break; case QRhi::D3D11: - setSurfaceType(OpenGLSurface); + setSurfaceType(Direct3DSurface); break; case QRhi::Metal: setSurfaceType(MetalSurface); diff --git a/tests/manual/rhi/multiwindow/multiwindow.cpp b/tests/manual/rhi/multiwindow/multiwindow.cpp index f48b931b01d..4a5345beb9d 100644 --- a/tests/manual/rhi/multiwindow/multiwindow.cpp +++ b/tests/manual/rhi/multiwindow/multiwindow.cpp @@ -330,12 +330,10 @@ Window::Window(const QString &title, const QColor &bgColor, int axis, bool noVSy #endif break; case D3D11: - setSurfaceType(OpenGLSurface); // not a typo + setSurfaceType(Direct3DSurface); break; case Metal: -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) setSurfaceType(MetalSurface); -#endif break; default: break; diff --git a/tests/manual/rhi/multiwindow_threaded/window.cpp b/tests/manual/rhi/multiwindow_threaded/window.cpp index aa7b4790476..d05543b4aee 100644 --- a/tests/manual/rhi/multiwindow_threaded/window.cpp +++ b/tests/manual/rhi/multiwindow_threaded/window.cpp @@ -75,12 +75,10 @@ Window::Window(const QString &title, GraphicsApi api) #endif break; case D3D11: - setSurfaceType(OpenGLSurface); // not a typo + setSurfaceType(Direct3DSurface); break; case Metal: -#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) setSurfaceType(MetalSurface); -#endif break; default: break; diff --git a/tests/manual/rhi/shared/examplefw.h b/tests/manual/rhi/shared/examplefw.h index 92e95313e89..282e3ec8d6e 100644 --- a/tests/manual/rhi/shared/examplefw.h +++ b/tests/manual/rhi/shared/examplefw.h @@ -192,7 +192,7 @@ Window::Window() setSurfaceType(VulkanSurface); break; case D3D11: - setSurfaceType(OpenGLSurface); // not a typo + setSurfaceType(Direct3DSurface); break; case Metal: #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))