Add a dedicated QWindow surface type for D3D

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ø <tor.arne.vestbo@qt.io>
This commit is contained in:
Laszlo Agocs 2021-01-04 10:27:11 +01:00 committed by Tor Arne Vestbø
parent 2d58620140
commit 97da4519ba
8 changed files with 32 additions and 27 deletions

View File

@ -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.
*/

View File

@ -69,7 +69,8 @@ public:
RasterGLSurface,
OpenVGSurface,
VulkanSurface,
MetalSurface
MetalSurface,
Direct3DSurface
};
Q_ENUM(SurfaceType)

View File

@ -351,6 +351,8 @@ static inline bool windowIsAccelerated(const QWindow *w)
return qt_window_private(const_cast<QWindow *>(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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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))