2022-05-10 10:06:48 +00:00
|
|
|
// Copyright (C) 2018 The Qt Company Ltd.
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
2019-03-22 08:55:03 +00:00
|
|
|
|
|
|
|
#include "window.h"
|
|
|
|
#include <QPlatformSurfaceEvent>
|
|
|
|
|
|
|
|
#if QT_CONFIG(vulkan)
|
|
|
|
extern QVulkanInstance *instance;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
Window::Window(const QString &title, GraphicsApi api)
|
|
|
|
{
|
|
|
|
switch (api) {
|
|
|
|
case OpenGL:
|
|
|
|
setSurfaceType(OpenGLSurface);
|
|
|
|
break;
|
|
|
|
case Vulkan:
|
|
|
|
setSurfaceType(VulkanSurface);
|
rhi: gl: Avoid magic adjustments to the context/window format
...by removing the entire adjustedFormat() helper.
Qt Quick has never used this, which indicates it is not that
useful. Same goes for Qt Multimedia or Qt 3D. Ensuring depth and
stencil is requested is already solved by using
QSurfaceFormat::setDefaultFormat() or by adjusting the formats
everywhere as appropriate.
The helper function's usages are in the manual tests that use it as a
shortcut, and in the GL backend itself. Remove it and leave it up the
client to set the depth or stencil buffer size, typically in the
global default surface format. (which in fact many of the mentioned
manual tests already did, so some of calls to
window->setFormat(adjustedFormat()) were completely unnecessary)
By not having the built-in magic that tries to always force depth and
stencil, we avoid problems that arise then the helper cannot be easily
invoked (thinking of widgets and backingstores), and so one ends up
with unexpected stencil (or depth) in the context (where the GL
backend auto-adjusts), but not in the window (which is not under
QRhi's control).
It was in practice possible to trigger EGL_BAD_MATCH failures with the
new rhi-based widget composition on EGL-based systems. For example, if
an application with a QOpenGLWidget did not set both depth and stencil
(but only one, or none), it ended up failing due to the context -
surface EGLConfig mismatches. On other platforms this matters less due
to less strict config/pixelformat management.
Pick-to: 6.4
Change-Id: I28ae2de163de63ee91bee3ceae08b58e106e1380
Fixes: QTBUG-104951
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
2022-07-15 12:16:23 +00:00
|
|
|
#if QT_CONFIG(vulkan)
|
2019-03-22 08:55:03 +00:00
|
|
|
setVulkanInstance(instance);
|
|
|
|
#endif
|
|
|
|
break;
|
|
|
|
case D3D11:
|
rhi: Make it a QPA-style private but semi-public API
qrhi.h, qshader.h, qshaderdescription.h (and qshaderbaker.h from
shadertools; done separately) become "RHI APIs", following the concept
of QPA APIs.
Mirror completely what is done for QPA headers, but using the "rhi"
prefix for the headers. This involves updating syncqt to handle the
new category of headers. (a note on the regex: matching everything
starting with "qrhi" is not acceptable due to incorrectly matching
existing and future headers, hence specifying the four header names
explicitly)
There is going to be one difference to QPA: the documentation for
everything RHI is going to be public and part of the regular docs, not
hidden with \internal.
In addition to the header renaming and adding the comments and
documentation notes and warnings, there is one significant change
here: there is no longer a need to do API-specific includes, such as
qrhid3d11[_p].h, qrhivulkan[_p].h, etc. These are simply merged into a
single header that is then included from qrhi.h. This means that users
within Qt, and any future applications can just do #include
<rhi/qrhi.h> (or rhi/qshader.h if the QRhi stuff is not relevant), no
other headers are needed.
There are no changes to functionality in this patch. Only the
documentation is expanded, quite a lot, to eliminate all qdoc warnings
and make the generated API docs complete. An example, with a quite
extensive doc page is added as well.
Task-number: QTBUG-113331
Change-Id: I91c749826348f14320cb335b1c83e9d1ea2b1d8b
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2023-04-27 11:16:29 +00:00
|
|
|
case D3D12:
|
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>
2021-01-04 09:27:11 +00:00
|
|
|
setSurfaceType(Direct3DSurface);
|
2019-03-22 08:55:03 +00:00
|
|
|
break;
|
|
|
|
case Metal:
|
|
|
|
setSurfaceType(MetalSurface);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
resize(800, 600);
|
|
|
|
setTitle(title);
|
|
|
|
}
|
|
|
|
|
|
|
|
Window::~Window()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void Window::exposeEvent(QExposeEvent *)
|
|
|
|
{
|
|
|
|
if (isExposed()) {
|
|
|
|
if (!m_running) {
|
|
|
|
// initialize and start rendering when the window becomes usable for graphics purposes
|
|
|
|
m_running = true;
|
|
|
|
m_notExposed = false;
|
|
|
|
emit initRequested();
|
|
|
|
emit renderRequested(true);
|
|
|
|
} else {
|
|
|
|
// continue when exposed again
|
|
|
|
if (m_notExposed) {
|
|
|
|
m_notExposed = false;
|
|
|
|
emit renderRequested(true);
|
|
|
|
} else {
|
|
|
|
// resize generates exposes - this is very important here (unlike in a single-threaded renderer)
|
|
|
|
emit syncSurfaceSizeRequested();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// stop pushing frames when not exposed (on some platforms this is essential, optional on others)
|
|
|
|
if (m_running)
|
|
|
|
m_notExposed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Window::event(QEvent *e)
|
|
|
|
{
|
|
|
|
switch (e->type()) {
|
|
|
|
case QEvent::UpdateRequest:
|
|
|
|
if (!m_notExposed)
|
|
|
|
emit renderRequested(false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case QEvent::PlatformSurface:
|
|
|
|
// this is the proper time to tear down the swapchain (while the native window and surface are still around)
|
|
|
|
if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
|
|
|
|
emit surfaceGoingAway();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return QWindow::event(e);
|
|
|
|
}
|