summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/.prev_CMakeLists.txt4
-rw-r--r--src/gui/CMakeLists.txt4
-rw-r--r--src/gui/accessible/qaccessible.h4
-rw-r--r--src/gui/image/image.pri2
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qimage.cpp4
-rw-r--r--src/gui/image/qimagereader.cpp2
-rw-r--r--src/gui/image/qimagereader.h4
-rw-r--r--src/gui/image/qimagewriter.cpp2
-rw-r--r--src/gui/image/qimagewriter.h4
-rw-r--r--src/gui/image/qpnghandler.cpp2
-rw-r--r--src/gui/kernel/qcursor.cpp4
-rw-r--r--src/gui/kernel/qcursor.h8
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp2
-rw-r--r--src/gui/kernel/qpixelformat.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.cpp29
-rw-r--r--src/gui/kernel/qplatformwindow.h4
-rw-r--r--src/gui/kernel/qscreen.cpp2
-rw-r--r--src/gui/kernel/qwindow.cpp72
-rw-r--r--src/gui/kernel/qwindow.h2
-rw-r--r--src/gui/painting/painting.pri2
-rw-r--r--src/gui/painting/qbackingstore.cpp2
-rw-r--r--src/gui/painting/qcolorspace.cpp28
-rw-r--r--src/gui/rhi/qrhi.cpp59
-rw-r--r--src/gui/rhi/qrhi_p.h17
-rw-r--r--src/gui/rhi/qrhi_p_p.h7
-rw-r--r--src/gui/rhi/qrhid3d11.cpp11
-rw-r--r--src/gui/rhi/qrhid3d11_p_p.h9
-rw-r--r--src/gui/rhi/qrhigles2.cpp17
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h9
-rw-r--r--src/gui/rhi/qrhimetal.mm151
-rw-r--r--src/gui/rhi/qrhimetal_p_p.h10
-rw-r--r--src/gui/rhi/qrhinull.cpp8
-rw-r--r--src/gui/rhi/qrhinull_p_p.h9
-rw-r--r--src/gui/rhi/qrhivulkan.cpp41
-rw-r--r--src/gui/rhi/qrhivulkan_p_p.h9
-rw-r--r--src/gui/text/qtextengine.cpp3
-rw-r--r--src/gui/text/qtextmarkdownimporter.cpp8
-rw-r--r--src/gui/text/qtextmarkdownwriter.cpp76
39 files changed, 466 insertions, 169 deletions
diff --git a/src/gui/.prev_CMakeLists.txt b/src/gui/.prev_CMakeLists.txt
index f8529ba650..933a8eae6d 100644
--- a/src/gui/.prev_CMakeLists.txt
+++ b/src/gui/.prev_CMakeLists.txt
@@ -456,7 +456,7 @@ if(NOT ANDROID)
)
endif()
-qt_extend_target(Gui CONDITION ANDROID AND TEST_architecture_arch STREQUAL arm64
+qt_extend_target(Gui CONDITION (NOT (NOT ANDROID)) AND (TEST_architecture_arch STREQUAL arm64 ORTEST_architecture_arch STREQUAL arm)
SOURCES
image/qimage_neon.cpp
painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
@@ -502,6 +502,8 @@ qt_extend_target(Gui CONDITION QT_FEATURE_system_textmarkdownreader AND QT_FEATU
qt_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader AND NOT QT_FEATURE_system_textmarkdownreader
SOURCES
../3rdparty/md4c/md4c.c ../3rdparty/md4c/md4c.h
+ DEFINES
+ MD4C_USE_UTF8
INCLUDE_DIRECTORIES
../3rdparty/md4c
)
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index ab1b3884cb..3e93b1ddea 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -538,7 +538,7 @@ if(NOT ANDROID)
)
endif()
-qt_extend_target(Gui CONDITION ANDROID AND TEST_architecture_arch STREQUAL arm64
+qt_extend_target(Gui CONDITION ANDROID AND (TEST_architecture_arch STREQUAL arm64 OR TEST_architecture_arch STREQUAL arm) # special case
SOURCES
image/qimage_neon.cpp
painting/qdrawhelper_neon.cpp painting/qdrawhelper_neon_p.h
@@ -603,6 +603,8 @@ qt_extend_target(Gui CONDITION QT_FEATURE_system_textmarkdownreader AND QT_FEATU
qt_extend_target(Gui CONDITION QT_FEATURE_textmarkdownreader AND NOT QT_FEATURE_system_textmarkdownreader
SOURCES
../3rdparty/md4c/md4c.c ../3rdparty/md4c/md4c.h
+ DEFINES
+ MD4C_USE_UTF8
INCLUDE_DIRECTORIES
../3rdparty/md4c
)
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 2220efd5cb..f7564a3076 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -280,7 +280,7 @@ public:
HotkeyField = 0x00000032,
Slider = 0x00000033,
SpinBox = 0x00000034,
- Canvas = 0x00000035, // Diagram for MSAA
+ Canvas = 0x00000035, // MSAA: ROLE_SYSTEM_DIAGRAM - The object represents a graphical image that is used to diagram data.
Animation = 0x00000036,
Equation = 0x00000037,
ButtonDropDown = 0x00000038, // The object represents a button that expands a grid.
@@ -302,7 +302,7 @@ public:
Notification = 0x00000086,
// IAccessible2 roles
- // IA2_ROLE_CANVAS = 0x401, ### Qt 6 use this one instead of Canvas above
+ // IA2_ROLE_CANVAS = 0x401, // An object that can be drawn into and to manage events from the objects drawn into it
// IA2_ROLE_CAPTION = 0x402,
// IA2_ROLE_CHECK_MENU_ITEM = 0x403,
ColorChooser = 0x404,
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index 760b737ec3..0c033609c4 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -92,7 +92,7 @@ qtConfig(png) {
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
} else {
# see https://developer.android.com/ndk/guides/abis
- arm64-v8a {
+ arm64-v8a | armeabi-v7a {
SOURCES += image/qimage_neon.cpp
}
x86 | x86_64 {
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 38285dd827..41fe649fc5 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1527,7 +1527,7 @@ QDebug operator<<(QDebug dbg, const QIcon &i)
\internal
\since 5.6
Attempts to find a suitable @Nx file for the given \a targetDevicePixelRatio
- Returns the the \a baseFileName if no such file was found.
+ Returns the \a baseFileName if no such file was found.
Given base foo.png and a target dpr of 2.5, this function will look for
foo@3x.png, then foo@2x, then fall back to foo.png if not found.
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 738aa29794..1319d9dffc 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1587,7 +1587,9 @@ const uchar *QImage::scanLine(int i) const
Returns a pointer to the pixel data at the scanline with index \a
i. The first scanline is at index 0.
- The scanline data is aligned on a 32-bit boundary.
+ The scanline data is as minimum 32-bit aligned. For 64-bit formats
+ it follows the native alignment of 64-bit integers (64-bit for most
+ platforms, but notably 32-bit on i386).
Note that QImage uses \l{Implicit Data Sharing} {implicit data
sharing}, but this function does \e not perform a deep copy of the
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 6139cf99c9..3eb1e01863 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -1149,6 +1149,7 @@ bool QImageReader::autoTransform() const
return false;
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
\since 5.6
@@ -1181,6 +1182,7 @@ float QImageReader::gamma() const
return d->handler->option(QImageIOHandler::Gamma).toFloat();
return 0.0;
}
+#endif
/*!
Returns \c true if an image can be read for the device (i.e., the
diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h
index 4e9a08b6e6..7cd3b81a7d 100644
--- a/src/gui/image/qimagereader.h
+++ b/src/gui/image/qimagereader.h
@@ -117,8 +117,12 @@ public:
void setAutoTransform(bool enabled);
bool autoTransform() const;
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
void setGamma(float gamma);
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
float gamma() const;
+#endif
QByteArray subType() const;
QList<QByteArray> supportedSubTypes() const;
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index 512da5c432..6e74b23f76 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -498,6 +498,7 @@ int QImageWriter::compression() const
return d->compression;
}
+#if QT_DEPRECATED_SINCE(5, 15)
/*!
This is an image format specific function that sets the gamma
level of the image to \a gamma. For image formats that do not
@@ -522,6 +523,7 @@ float QImageWriter::gamma() const
{
return d->gamma;
}
+#endif
/*!
\since 5.4
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index ef84a59b7c..5c8ed7e211 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -84,8 +84,12 @@ public:
void setCompression(int compression);
int compression() const;
+#if QT_DEPRECATED_SINCE(5, 15)
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
void setGamma(float gamma);
+ QT_DEPRECATED_VERSION_X_5_15("Use QColorSpace instead")
float gamma() const;
+#endif
void setSubType(const QByteArray &type);
QByteArray subType() const;
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 49f9550519..8435e5a0fe 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -606,7 +606,7 @@ bool QPngHandlerPrivate::readPngHeader()
#endif
png_uint_32 profLen;
png_get_iCCP(png_ptr, info_ptr, &name, &compressionType, &profileData, &profLen);
- colorSpace = QColorSpace::fromIccProfile(QByteArray::fromRawData((const char *)profileData, profLen));
+ colorSpace = QColorSpace::fromIccProfile(QByteArray((const char *)profileData, profLen));
if (!colorSpace.isValid()) {
qWarning() << "QPngHandler: Failed to parse ICC profile";
} else {
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 7f6fdafbd0..1efa28a5af 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -621,7 +621,7 @@ const QBitmap *QCursor::mask() const
QBitmap bmpVal = cursor->bitmap();
\endcode
*/
-QBitmap QCursor::bitmap(Qt::ReturnByValue_t) const
+QBitmap QCursor::bitmap(Qt::ReturnByValueConstant) const
{
if (!QCursorData::initialized)
QCursorData::initialize();
@@ -653,7 +653,7 @@ QBitmap QCursor::bitmap(Qt::ReturnByValue_t) const
QBitmap bmpVal = cursor->mask();
\endcode
*/
-QBitmap QCursor::mask(Qt::ReturnByValue_t) const
+QBitmap QCursor::mask(Qt::ReturnByValueConstant) const
{
if (!QCursorData::initialized)
QCursorData::initialize();
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index 7a11fe59ee..3ae6b98ced 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -104,11 +104,11 @@ public:
QT_DEPRECATED_VERSION_X(5, 15, "Use the other overload which returns QBitmap by-value")
const QBitmap *mask() const; // ### Qt 7: Remove function
- QBitmap bitmap(Qt::ReturnByValue_t) const;
- QBitmap mask(Qt::ReturnByValue_t) const;
+ QBitmap bitmap(Qt::ReturnByValueConstant) const;
+ QBitmap mask(Qt::ReturnByValueConstant) const;
#else
- QBitmap bitmap(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
- QBitmap mask(Qt::ReturnByValue_t = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QBitmap bitmap(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
+ QBitmap mask(Qt::ReturnByValueConstant = Qt::ReturnByValue) const; // ### Qt 7: Remove arg
#endif // QT_DEPRECATED_SINCE(5, 15)
QPixmap pixmap() const;
QPoint hotSpot() const;
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index fde6bb0180..671c2d93ef 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -535,7 +535,7 @@ void QHighDpiScaling::updateHighDpiScaling()
++i;
}
}
- m_active = m_globalScalingActive || m_screenFactorSet || m_usePixelDensity;
+ m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
}
/*
diff --git a/src/gui/kernel/qpixelformat.cpp b/src/gui/kernel/qpixelformat.cpp
index c28fe7ac63..3100d13398 100644
--- a/src/gui/kernel/qpixelformat.cpp
+++ b/src/gui/kernel/qpixelformat.cpp
@@ -485,7 +485,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn ByteOrder QPixelFormat::byteOrder() const
- The byte order is almost always set the the byte order of the current
+ The byte order is almost always set the byte order of the current
system. However, it can be useful to describe some YUV formats. This
function should never return QPixelFormat::CurrentSystemEndian as this
value is translated to a endian value in the constructor.
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 65accc9f68..15d7505133 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -482,19 +482,17 @@ bool QPlatformWindow::windowEvent(QEvent *event)
}
/*!
- Reimplement this method to start a system size grip drag
- operation if the system supports it and return true to indicate
- success.
- It is called from the mouse press event handler of the size grip.
+ Reimplement this method to start a system resize operation if
+ the system supports it and return true to indicate success.
+
+ The default implementation is empty and does nothing with \a edges.
- The default implementation is empty and does nothing with \a pos
- and \a corner.
+ \since 5.15
*/
-bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
+bool QPlatformWindow::startSystemResize(Qt::Edges edges)
{
- Q_UNUSED(pos)
- Q_UNUSED(corner)
+ Q_UNUSED(edges)
return false;
}
@@ -502,18 +500,13 @@ bool QPlatformWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
Reimplement this method to start a system move operation if
the system supports it and return true to indicate success.
- The \a pos is a position of MouseButtonPress event or TouchBegin
- event from a sequence of mouse events that triggered the movement.
- It must be specified in window coordinates.
-
- The default implementation is empty and does nothing with \a pos.
+ The default implementation is empty and does nothing.
- \since 5.11
+ \since 5.15
*/
-bool QPlatformWindow::startSystemMove(const QPoint &pos)
+bool QPlatformWindow::startSystemMove()
{
- Q_UNUSED(pos)
return false;
}
@@ -747,7 +740,7 @@ QRect QPlatformWindow::initialGeometry(const QWindow *w, const QRect &initialGeo
QPlatformWindow subclasses can re-implement this function to
provide display refresh synchronized updates. The event
should be delivered using QPlatformWindow::deliverUpdateRequest()
- to not get out of sync with the the internal state of QWindow.
+ to not get out of sync with the internal state of QWindow.
The default implementation posts an UpdateRequest event to the
window after 5 ms. The additional time is there to give the event
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index b6aeb3a86a..7b85090cc0 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -132,8 +132,8 @@ public:
virtual bool windowEvent(QEvent *event);
- virtual bool startSystemResize(const QPoint &pos, Qt::Corner corner);
- virtual bool startSystemMove(const QPoint &pos);
+ virtual bool startSystemResize(Qt::Edges edges);
+ virtual bool startSystemMove();
virtual void setFrameStrutEventsEnabled(bool enabled);
virtual bool frameStrutEventsEnabled() const;
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 9de59f8c7e..fd25becbca 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -149,6 +149,8 @@ QScreen::~QScreen()
/*!
Get the platform screen handle.
+
+ \sa {Qt Platform Abstraction}{Qt Platform Abstraction (QPA)}
*/
QPlatformScreen *QScreen::handle() const
{
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index dad1b6ba2d..c099ec9692 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1051,6 +1051,71 @@ void QWindow::lower()
}
/*!
+ \brief Start a system-specific resize operation
+ \since 5.15
+
+ Calling this will start an interactive resize operation on the window by platforms
+ that support it. The actual behavior may vary depending on the platform. Usually,
+ it will make the window resize so that its edge follows the mouse cursor.
+
+ On platforms that support it, this method of resizing windows is preferred over
+ \c setGeometry, because it allows a more native look-and-feel of resizing windows, e.g.
+ letting the window manager snap this window against other windows, or special resizing
+ behavior with animations when dragged to the edge of the screen.
+
+ \a edges should either be a single edge, or two adjacent edges (a corner). Other values
+ are not allowed.
+
+ Returns true if the operation was supported by the system.
+*/
+bool QWindow::startSystemResize(Qt::Edges edges)
+{
+ Q_D(QWindow);
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow || d->maximumSize == d->minimumSize))
+ return false;
+
+ const bool isSingleEdge = edges == Qt::TopEdge || edges == Qt::RightEdge || edges == Qt::BottomEdge || edges == Qt::LeftEdge;
+ const bool isCorner =
+ edges == (Qt::TopEdge | Qt::LeftEdge) ||
+ edges == (Qt::TopEdge | Qt::RightEdge) ||
+ edges == (Qt::BottomEdge | Qt::RightEdge) ||
+ edges == (Qt::BottomEdge | Qt::LeftEdge);
+
+ if (Q_UNLIKELY(!isSingleEdge && !isCorner)) {
+ qWarning() << "Invalid edges" << edges << "passed to QWindow::startSystemResize, ignoring.";
+ return false;
+ }
+
+ return d->platformWindow->startSystemResize(edges);
+}
+
+/*!
+ \brief Start a system-specific move operation
+ \since 5.15
+
+ Calling this will start an interactive move operation on the window by platforms
+ that support it. The actual behavior may vary depending on the platform. Usually,
+ it will make the window follow the mouse cursor until a mouse button is released.
+
+ On platforms that support it, this method of moving windows is preferred over
+ \c setPosition, because it allows a more native look-and-feel of moving windows, e.g.
+ letting the window manager snap this window against other windows, or special tiling
+ or resizing behavior with animations when dragged to the edge of the screen.
+ Furthermore, on some platforms such as Wayland, \c setPosition is not supported, so
+ this is the only way the application can influence its position.
+
+ Returns true if the operation was supported by the system.
+*/
+bool QWindow::startSystemMove()
+{
+ Q_D(QWindow);
+ if (Q_UNLIKELY(!isVisible() || !d->platformWindow))
+ return false;
+
+ return d->platformWindow->startSystemMove();
+}
+
+/*!
\property QWindow::opacity
\brief The opacity of the window in the windowing system.
\since 5.1
@@ -1793,7 +1858,10 @@ void QWindow::setFramePosition(const QPoint &point)
The position is in relation to the virtualGeometry() of its screen.
- \sa position()
+ For interactively moving windows, see startSystemMove(). For interactively
+ resizing windows, see startSystemResize().
+
+ \sa position(), startSystemMove()
*/
void QWindow::setPosition(const QPoint &pt)
{
@@ -1830,6 +1898,8 @@ void QWindow::setPosition(int posx, int posy)
set the size of the window, excluding any window frame, to a QSize
constructed from width \a w and height \a h
+ For interactively resizing windows, see startSystemResize().
+
\sa size(), geometry()
*/
void QWindow::resize(int w, int h)
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 5ee1d00f5b..7aae7ffffa 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -292,6 +292,8 @@ public Q_SLOTS:
bool close();
void raise();
void lower();
+ bool startSystemResize(Qt::Edges edges);
+ bool startSystemMove();
void setTitle(const QString &);
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 1a0f4f11e4..94a88f55dc 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -161,7 +161,7 @@ gcc:equals(QT_GCC_MAJOR_VERSION, 5) {
DEFINES += QT_COMPILER_SUPPORTS_SSE4_1 QT_COMPILER_SUPPORTS_SSE4_2
SOURCES += painting/qdrawhelper_sse4.cpp painting/qimagescale_sse4.cpp
}
- arm64-v8a {
+ arm64-v8a | armeabi-v7a {
SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
HEADERS += painting/qdrawhelper_neon_p.h
}
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 0a49269c36..2147d9d61d 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -281,7 +281,7 @@ QSize QBackingStore::size() const
bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{
// Disable scrolling for non-integer scroll deltas. For this case
- // the the existing rendered pixels can't be re-used, and we return
+ // the existing rendered pixels can't be re-used, and we return
// false to signal that a repaint is needed.
const qreal nativeDx = QHighDpi::toNativePixels(qreal(dx), d_ptr->window);
const qreal nativeDy = QHighDpi::toNativePixels(qreal(dy), d_ptr->window);
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 7ebd5f1bf4..7e7bbec870 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -549,8 +549,12 @@ float QColorSpace::gamma() const noexcept
*/
void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma)
{
- if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom)
+ if (transferFunction == TransferFunction::Custom)
+ return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(Primaries::Custom, transferFunction, gamma);
return;
+ }
if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
return;
QColorSpacePrivate::getWritable(*this); // detach
@@ -585,8 +589,12 @@ QColorSpace QColorSpace::withTransferFunction(QColorSpace::TransferFunction tran
*/
void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
{
- if (!isValid() || primariesId == QColorSpace::Primaries::Custom)
+ if (primariesId == Primaries::Custom)
return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(primariesId, TransferFunction::Custom, 0.0f);
+ return;
+ }
if (d_ptr->primaries == primariesId)
return;
QColorSpacePrivate::getWritable(*this); // detach
@@ -605,11 +613,13 @@ void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoint,
const QPointF &greenPoint, const QPointF &bluePoint)
{
- if (!isValid())
- return;
QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint);
if (!primaries.areValid())
return;
+ if (!d_ptr) {
+ d_ptr = new QColorSpacePrivate(primaries, TransferFunction::Custom, 0.0f);
+ return;
+ }
QColorMatrix toXyz = primaries.toXyzMatrix();
if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz)
return;
@@ -692,12 +702,14 @@ bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2)
const bool valid1 = colorSpace1.isValid();
const bool valid2 = colorSpace2.isValid();
- if (!valid1 && !valid2)
- return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile;
- else if (!valid1 || !valid2)
+ if (valid1 != valid2)
return false;
+ if (!valid1 && !valid2) {
+ if (!colorSpace1.d_ptr->iccProfile.isEmpty() || !colorSpace2.d_ptr->iccProfile.isEmpty())
+ return colorSpace1.d_ptr->iccProfile == colorSpace2.d_ptr->iccProfile;
+ }
- // At this point one or both color spaces are unknown but valid, and must be compared in detail instead
+ // At this point one or both color spaces are unknown, and must be compared in detail instead
if (colorSpace1.primaries() != QColorSpace::Primaries::Custom && colorSpace2.primaries() != QColorSpace::Primaries::Custom) {
if (colorSpace1.primaries() != colorSpace2.primaries())
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index a9c6835687..f0bf19bd91 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -1652,7 +1652,7 @@ QRhiTextureUploadDescription::QRhiTextureUploadDescription(const QRhiTextureUplo
Constructs a texture upload description with the specified \a list of entries.
\note \a list can also contain multiple QRhiTextureUploadEntry elements
- with the the same layer and level. This makes sense when those uploads are
+ with the same layer and level. This makes sense when those uploads are
partial, meaning their subresource description has a source size or image
smaller than the subresource dimensions, and can be more efficient than
issuing separate uploadTexture()'s.
@@ -2297,11 +2297,10 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
*/
QRhiSampler::QRhiSampler(QRhiImplementation *rhi,
Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_)
+ AddressMode u_, AddressMode v_, AddressMode w_)
: QRhiResource(rhi),
m_magFilter(magFilter_), m_minFilter(minFilter_), m_mipmapMode(mipmapMode_),
- m_addressU(u_), m_addressV(v_),
- m_addressW(QRhiSampler::ClampToEdge),
+ m_addressU(u_), m_addressV(v_), m_addressW(w_),
m_compareOp(QRhiSampler::Never)
{
}
@@ -3506,7 +3505,7 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
\l{QSurfaceFormat::sRGBColorSpace}{sRGBColorSpace} on the QSurfaceFormat of
the QWindow in addition.
- \value UsedAsTransferSource Indicates the the swapchain will be used as the
+ \value UsedAsTransferSource Indicates the swapchain will be used as the
source of a readback in QRhiResourceUpdateBatch::readBackTexture().
\value NoVSync Requests disabling waiting for vertical sync, also avoiding
@@ -3623,7 +3622,7 @@ QRhiResource::Type QRhiSwapChain::resourceType() const
\fn QRhiRenderTarget *QRhiSwapChain::currentFrameRenderTarget()
\return a render target that can used with beginPass() in order to render
- the the swapchain's current backbuffer. Only valid within a
+ the swapchain's current backbuffer. Only valid within a
QRhi::beginFrame() - QRhi::endFrame() block where beginFrame() was called
with this swapchain.
@@ -4449,7 +4448,7 @@ void QRhiResourceUpdateBatch::generateMips(QRhiTexture *tex, int layer)
recorded.
\note the return value is not owned by the caller and must never be
- destroyed. Instead, the batch is returned the the pool for reuse by passing
+ destroyed. Instead, the batch is returned the pool for reuse by passing
it to QRhiCommandBuffer::beginPass(), QRhiCommandBuffer::endPass(), or
QRhiCommandBuffer::resourceUpdate(), or by calling
QRhiResourceUpdateBatch::release() on it.
@@ -5059,13 +5058,24 @@ bool QRhi::isYUpInNDC() const
}
/*!
- \return \c true if the underlying graphics API uses depth 0 - 1 in clip
- space.
+ \return \c true if the underlying graphics API uses depth range [0, 1] in
+ clip space.
- In practice this is \c false for OpenGL only.
+ In practice this is \c false for OpenGL only, because OpenGL uses a
+ post-projection depth range of [-1, 1]. (not to be confused with the
+ NDC-to-window mapping controlled by glDepthRange(), which uses a range of
+ [0, 1], unless overridden by the QRhiViewport) In some OpenGL versions
+ glClipControl() could be used to change this, but the OpenGL backend of
+ QRhi does not use that function as it is not available in OpenGL ES or
+ OpenGL versions lower than 4.5.
\note clipSpaceCorrMatrix() includes the corresponding adjustment in its
- returned matrix.
+ returned matrix. Therefore, many users of QRhi do not need to take any
+ further measures apart from pre-multiplying their projection matrices with
+ clipSpaceCorrMatrix(). However, some graphics techniques, such as, some
+ types of shadow mapping, involve working with and outputting depth values
+ in the shaders. These will need to query and take the value of this
+ function into account as appropriate.
*/
bool QRhi::isClipDepthZeroToOne() const
{
@@ -5075,11 +5085,15 @@ bool QRhi::isClipDepthZeroToOne() const
/*!
\return a matrix that can be used to allow applications keep using
OpenGL-targeted vertex data and perspective projection matrices (such as,
- the ones generated by QMatrix4x4::perspective()), regardless of the
- backend. Once \c{this_matrix * mvp} is used instead of just \c mvp, vertex
- data with Y up and viewports with depth range 0 - 1 can be used without
- considering what backend and so graphics API is going to be used at run
- time.
+ the ones generated by QMatrix4x4::perspective()), regardless of the active
+ QRhi backend.
+
+ In a typical renderer, once \c{this_matrix * mvp} is used instead of just
+ \c mvp, vertex data with Y up and viewports with depth range 0 - 1 can be
+ used without considering what backend (and so graphics API) is going to be
+ used at run time. This way branching based on isYUpInNDC() and
+ isClipDepthZeroToOne() can be avoided (although such logic may still become
+ required when implementing certain advanced graphics techniques).
See
\l{https://matthewwellings.com/blog/the-new-vulkan-coordinate-system/}{this
@@ -5321,16 +5335,19 @@ QRhiTexture *QRhi::newTexture(QRhiTexture::Format format,
/*!
\return a new sampler with the specified magnification filter \a magFilter,
- minification filter \a minFilter, mipmapping mode \a mipmapMpde, and S/T
- addressing modes \a u and \a v.
+ minification filter \a minFilter, mipmapping mode \a mipmapMode, and the
+ addressing (wrap) modes \a addressU, \a addressV, and \a addressW.
\sa QRhiResource::release()
*/
-QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+QRhiSampler *QRhi::newSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode addressU,
+ QRhiSampler::AddressMode addressV,
+ QRhiSampler::AddressMode addressW)
{
- return d->createSampler(magFilter, minFilter, mipmapMode, u, v);
+ return d->createSampler(magFilter, minFilter, mipmapMode, addressU, addressV, addressW);
}
/*!
diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h
index 3a64835c22..d17112a241 100644
--- a/src/gui/rhi/qrhi_p.h
+++ b/src/gui/rhi/qrhi_p.h
@@ -850,7 +850,7 @@ public:
protected:
QRhiSampler(QRhiImplementation *rhi,
Filter magFilter_, Filter minFilter_, Filter mipmapMode_,
- AddressMode u_, AddressMode v_);
+ AddressMode u_, AddressMode v_, AddressMode w_);
Filter m_magFilter;
Filter m_minFilter;
Filter m_mipmapMode;
@@ -1155,6 +1155,12 @@ public:
float lineWidth() const { return m_lineWidth; }
void setLineWidth(float width) { m_lineWidth = width; }
+ int depthBias() const { return m_depthBias; }
+ void setDepthBias(int bias) { m_depthBias = bias; }
+
+ float slopeScaledDepthBias() const { return m_slopeScaledDepthBias; }
+ void setSlopeScaledDepthBias(float bias) { m_slopeScaledDepthBias = bias; }
+
void setShaderStages(std::initializer_list<QRhiShaderStage> list) { m_shaderStages = list; }
template<typename InputIterator>
void setShaderStages(InputIterator first, InputIterator last)
@@ -1193,6 +1199,8 @@ protected:
quint32 m_stencilWriteMask = 0xFF;
int m_sampleCount = 1;
float m_lineWidth = 1.0f;
+ int m_depthBias = 0;
+ float m_slopeScaledDepthBias = 0.0f;
QVarLengthArray<QRhiShaderStage, 4> m_shaderStages;
QRhiVertexInputLayout m_vertexInputLayout;
QRhiShaderResourceBindings *m_shaderResourceBindings = nullptr;
@@ -1474,9 +1482,12 @@ public:
int sampleCount = 1,
QRhiTexture::Flags flags = QRhiTexture::Flags());
- QRhiSampler *newSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *newSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v);
+ QRhiSampler::AddressMode addressU,
+ QRhiSampler::AddressMode addressV,
+ QRhiSampler::AddressMode addressW = QRhiSampler::Repeat);
QRhiTextureRenderTarget *newTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags = QRhiTextureRenderTarget::Flags());
diff --git a/src/gui/rhi/qrhi_p_p.h b/src/gui/rhi/qrhi_p_p.h
index baffe28202..4a4c044a29 100644
--- a/src/gui/rhi/qrhi_p_p.h
+++ b/src/gui/rhi/qrhi_p_p.h
@@ -85,9 +85,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) = 0;
- virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ virtual QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) = 0;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) = 0;
virtual QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) = 0;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 445d162595..75b90b6995 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -527,9 +527,9 @@ QRhiTexture *QRhiD3D11::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiD3D11::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QD3D11Sampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiD3D11::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -2768,8 +2768,8 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
}
QD3D11Sampler::QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
@@ -3467,6 +3467,9 @@ bool QD3D11GraphicsPipeline::build()
rastDesc.FillMode = D3D11_FILL_SOLID;
rastDesc.CullMode = toD3DCullMode(m_cullMode);
rastDesc.FrontCounterClockwise = m_frontFace == CCW;
+ rastDesc.DepthBias = m_depthBias;
+ rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
+ rastDesc.DepthClipEnable = true;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
rastDesc.MultisampleEnable = rhiD->effectiveSampleCount(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
diff --git a/src/gui/rhi/qrhid3d11_p_p.h b/src/gui/rhi/qrhid3d11_p_p.h
index 9ddd2aa797..c3a4021241 100644
--- a/src/gui/rhi/qrhid3d11_p_p.h
+++ b/src/gui/rhi/qrhid3d11_p_p.h
@@ -120,7 +120,7 @@ struct QD3D11Texture : public QRhiTexture
struct QD3D11Sampler : public QRhiSampler
{
QD3D11Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QD3D11Sampler();
void release() override;
bool build() override;
@@ -559,9 +559,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index ec5e531e14..62f808ce81 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -838,9 +838,9 @@ QRhiTexture *QRhiGles2::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiGles2::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QGles2Sampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiGles2::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -2386,7 +2386,14 @@ void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps)
f->glDisable(GL_STENCIL_TEST);
}
- if (psD->topology() == QRhiGraphicsPipeline::Lines || psD->topology() == QRhiGraphicsPipeline::LineStrip)
+ if (psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias)) {
+ f->glPolygonOffset(psD->m_slopeScaledDepthBias, psD->m_depthBias);
+ f->glEnable(GL_POLYGON_OFFSET_FILL);
+ } else {
+ f->glDisable(GL_POLYGON_OFFSET_FILL);
+ }
+
+ if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip)
f->glLineWidth(psD->m_lineWidth);
f->glUseProgram(psD->program);
@@ -3626,8 +3633,8 @@ QRhiTexture::NativeTexture QGles2Texture::nativeTexture()
}
QGles2Sampler::QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 679f806004..00caf40118 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -170,7 +170,7 @@ struct QGles2Texture : public QRhiTexture
struct QGles2Sampler : public QRhiSampler
{
QGles2Sampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QGles2Sampler();
void release() override;
bool build() override;
@@ -613,9 +613,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 98cbd416b5..9e8f1ac096 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -298,6 +298,8 @@ struct QMetalGraphicsPipelineData
MTLPrimitiveType primitiveType;
MTLWinding winding;
MTLCullMode cullMode;
+ float depthBias;
+ float slopeScaledDepthBias;
QMetalShader vs;
QMetalShader fs;
};
@@ -626,9 +628,9 @@ QRhiTexture *QRhiMetal::createTexture(QRhiTexture::Format format, const QSize &p
QRhiSampler *QRhiMetal::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QMetalSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiMetal::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -684,11 +686,27 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
bool offsetOnlyChange,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[SUPPORTED_STAGES])
{
- struct {
- QRhiBatchedBindings<id<MTLBuffer> > buffers;
- QRhiBatchedBindings<NSUInteger> bufferOffsets;
- QRhiBatchedBindings<id<MTLTexture> > textures;
- QRhiBatchedBindings<id<MTLSamplerState> > samplers;
+ struct Stage {
+ struct Buffer {
+ int nativeBinding;
+ id<MTLBuffer> mtlbuf;
+ uint offset;
+ };
+ struct Texture {
+ int nativeBinding;
+ id<MTLTexture> mtltex;
+ };
+ struct Sampler {
+ int nativeBinding;
+ id<MTLSamplerState> mtlsampler;
+ };
+ QVarLengthArray<Buffer, 8> buffers;
+ QVarLengthArray<Texture, 8> textures;
+ QVarLengthArray<Sampler, 8> samplers;
+ QRhiBatchedBindings<id<MTLBuffer> > bufferBatches;
+ QRhiBatchedBindings<NSUInteger> bufferOffsetBatches;
+ QRhiBatchedBindings<id<MTLTexture> > textureBatches;
+ QRhiBatchedBindings<id<MTLSamplerState> > samplerBatches;
} res[SUPPORTED_STAGES];
enum { VERTEX = 0, FRAGMENT = 1, COMPUTE = 2 };
@@ -709,24 +727,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
}
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[VERTEX].buffers.feed(nativeBinding, mtlbuf);
- res[VERTEX].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf);
- res[FRAGMENT].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[COMPUTE].buffers.feed(nativeBinding, mtlbuf);
- res[COMPUTE].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
}
}
break;
@@ -738,24 +750,24 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[VERTEX].textures.feed(nativeBindingTexture, texD->d->tex);
- res[VERTEX].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[VERTEX].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[VERTEX].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[FRAGMENT].textures.feed(nativeBindingTexture, texD->d->tex);
- res[FRAGMENT].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[FRAGMENT].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[FRAGMENT].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler);
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
- res[COMPUTE].textures.feed(nativeBindingTexture, texD->d->tex);
- res[COMPUTE].samplers.feed(nativeBindingSampler, samplerD->d->samplerState);
+ res[COMPUTE].textures.append({ nativeBindingTexture, texD->d->tex });
+ res[COMPUTE].samplers.append({ nativeBindingSampler, samplerD->d->samplerState });
}
}
}
@@ -769,17 +781,17 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[VERTEX].textures.feed(nativeBinding, t);
+ res[VERTEX].textures.append({ nativeBinding, t });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[FRAGMENT].textures.feed(nativeBinding, t);
+ res[FRAGMENT].textures.append({ nativeBinding, t });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
if (nativeBinding >= 0)
- res[COMPUTE].textures.feed(nativeBinding, t);
+ res[COMPUTE].textures.append({ nativeBinding, t });
}
}
break;
@@ -792,24 +804,18 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
uint offset = uint(b->u.sbuf.offset);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
const int nativeBinding = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[VERTEX].buffers.feed(nativeBinding, mtlbuf);
- res[VERTEX].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[VERTEX].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
const int nativeBinding = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[FRAGMENT].buffers.feed(nativeBinding, mtlbuf);
- res[FRAGMENT].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[FRAGMENT].buffers.append({ nativeBinding, mtlbuf, offset });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
const int nativeBinding = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Buffer);
- if (nativeBinding >= 0) {
- res[COMPUTE].buffers.feed(nativeBinding, mtlbuf);
- res[COMPUTE].bufferOffsets.feed(b->binding, offset);
- }
+ if (nativeBinding >= 0)
+ res[COMPUTE].buffers.append({ nativeBinding, mtlbuf, offset });
}
}
break;
@@ -825,12 +831,26 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (cbD->recordingPass != QMetalCommandBuffer::ComputePass && stage == COMPUTE)
continue;
- res[stage].buffers.finish();
- res[stage].bufferOffsets.finish();
+ // QRhiBatchedBindings works with the native bindings and expects
+ // sorted input. The pre-sorted QRhiShaderResourceBinding list (based
+ // on the QRhi (SPIR-V) binding) is not helpful in this regard, so we
+ // have to sort here every time.
+
+ std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
+
+ for (const Stage::Buffer &buf : qAsConst(res[stage].buffers)) {
+ res[stage].bufferBatches.feed(buf.nativeBinding, buf.mtlbuf);
+ res[stage].bufferOffsetBatches.feed(buf.nativeBinding, buf.offset);
+ }
+
+ res[stage].bufferBatches.finish();
+ res[stage].bufferOffsetBatches.finish();
- for (int i = 0, ie = res[stage].buffers.batches.count(); i != ie; ++i) {
- const auto &bufferBatch(res[stage].buffers.batches[i]);
- const auto &offsetBatch(res[stage].bufferOffsets.batches[i]);
+ for (int i = 0, ie = res[stage].bufferBatches.batches.count(); i != ie; ++i) {
+ const auto &bufferBatch(res[stage].bufferBatches.batches[i]);
+ const auto &offsetBatch(res[stage].bufferOffsetBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexBuffers: bufferBatch.resources.constData()
@@ -856,11 +876,25 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
if (offsetOnlyChange)
continue;
- res[stage].textures.finish();
- res[stage].samplers.finish();
+ std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
- for (int i = 0, ie = res[stage].textures.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].textures.batches[i]);
+ std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
+ return a.nativeBinding < b.nativeBinding;
+ });
+
+ for (const Stage::Texture &t : qAsConst(res[stage].textures))
+ res[stage].textureBatches.feed(t.nativeBinding, t.mtltex);
+
+ for (const Stage::Sampler &s : qAsConst(res[stage].samplers))
+ res[stage].samplerBatches.feed(s.nativeBinding, s.mtlsampler);
+
+ res[stage].textureBatches.finish();
+ res[stage].samplerBatches.finish();
+
+ for (int i = 0, ie = res[stage].textureBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(res[stage].textureBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexTextures: batch.resources.constData()
@@ -879,8 +913,8 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
break;
}
}
- for (int i = 0, ie = res[stage].samplers.batches.count(); i != ie; ++i) {
- const auto &batch(res[stage].samplers.batches[i]);
+ for (int i = 0, ie = res[stage].samplerBatches.batches.count(); i != ie; ++i) {
+ const auto &batch(res[stage].samplerBatches.batches[i]);
switch (stage) {
case VERTEX:
[cbD->d->currentRenderPassEncoder setVertexSamplerStates: batch.resources.constData()
@@ -924,6 +958,14 @@ void QRhiMetal::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
[cbD->d->currentRenderPassEncoder setFrontFacingWinding: psD->d->winding];
cbD->currentFrontFaceWinding = int(psD->d->winding);
}
+ if (!qFuzzyCompare(psD->d->depthBias, cbD->currentDepthBiasValues.first)
+ || !qFuzzyCompare(psD->d->slopeScaledDepthBias, cbD->currentDepthBiasValues.second))
+ {
+ [cbD->d->currentRenderPassEncoder setDepthBias: psD->d->depthBias
+ slopeScale: psD->d->slopeScaledDepthBias
+ clamp: 0.0f];
+ cbD->currentDepthBiasValues = { psD->d->depthBias, psD->d->slopeScaledDepthBias };
+ }
}
psD->lastActiveFrameSlot = currentFrameSlot;
@@ -2548,8 +2590,8 @@ id<MTLTexture> QMetalTextureData::viewForLevel(int level)
}
QMetalSampler::QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v),
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w),
d(new QMetalSamplerData)
{
}
@@ -3422,6 +3464,8 @@ bool QMetalGraphicsPipeline::build()
d->primitiveType = toMetalPrimitiveType(m_topology);
d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
d->cullMode = toMetalCullMode(m_cullMode);
+ d->depthBias = float(m_depthBias);
+ d->slopeScaledDepthBias = m_slopeScaledDepthBias;
lastActiveFrameSlot = -1;
generation += 1;
@@ -3570,6 +3614,7 @@ void QMetalCommandBuffer::resetPerPassCachedState()
currentIndexFormat = QRhiCommandBuffer::IndexUInt16;
currentCullMode = -1;
currentFrontFaceWinding = -1;
+ currentDepthBiasValues = { 0.0f, 0.0f };
d->currentFirstVertexBinding = -1;
d->currentVertexInputsBuffers.clear();
diff --git a/src/gui/rhi/qrhimetal_p_p.h b/src/gui/rhi/qrhimetal_p_p.h
index 71d4325b1a..58e93e2cdb 100644
--- a/src/gui/rhi/qrhimetal_p_p.h
+++ b/src/gui/rhi/qrhimetal_p_p.h
@@ -120,7 +120,7 @@ struct QMetalSamplerData;
struct QMetalSampler : public QRhiSampler
{
QMetalSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QMetalSampler();
void release() override;
bool build() override;
@@ -288,6 +288,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
QRhiCommandBuffer::IndexFormat currentIndexFormat;
int currentCullMode;
int currentFrontFaceWinding;
+ QPair<float, float> currentDepthBiasValues;
const QRhiNativeHandles *nativeHandles();
void resetState();
@@ -349,9 +350,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhinull.cpp b/src/gui/rhi/qrhinull.cpp
index ea67f80138..4c59900aa6 100644
--- a/src/gui/rhi/qrhinull.cpp
+++ b/src/gui/rhi/qrhinull.cpp
@@ -193,9 +193,9 @@ QRhiTexture *QRhiNull::createTexture(QRhiTexture::Format format, const QSize &pi
QRhiSampler *QRhiNull::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QNullSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiNull::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -645,8 +645,8 @@ bool QNullTexture::buildFrom(QRhiTexture::NativeTexture src)
}
QNullSampler::QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
diff --git a/src/gui/rhi/qrhinull_p_p.h b/src/gui/rhi/qrhinull_p_p.h
index f541fd90b8..0b3d40f1aa 100644
--- a/src/gui/rhi/qrhinull_p_p.h
+++ b/src/gui/rhi/qrhinull_p_p.h
@@ -88,7 +88,7 @@ struct QNullTexture : public QRhiTexture
struct QNullSampler : public QRhiSampler
{
QNullSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QNullSampler();
void release() override;
bool build() override;
@@ -212,9 +212,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index e7faa0cadd..84ca835392 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -2462,9 +2462,10 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
{
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
- QVarLengthArray<VkDescriptorBufferInfo, 4> bufferInfos;
- QVarLengthArray<VkDescriptorImageInfo, 4> imageInfos;
- QVarLengthArray<VkWriteDescriptorSet, 8> writeInfos;
+ QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos;
+ QVarLengthArray<VkDescriptorImageInfo, 8> imageInfos;
+ QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos;
+ QVarLengthArray<QPair<int, int>, 12> infoIndices;
const bool updateAll = descSetIdx < 0;
int frameSlot = updateAll ? 0 : descSetIdx;
@@ -2481,6 +2482,9 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
writeInfo.dstBinding = uint32_t(b->binding);
writeInfo.descriptorCount = 1;
+ int bufferInfoIndex = -1;
+ int imageInfoIndex = -1;
+
switch (b->type) {
case QRhiShaderResourceBinding::UniformBuffer:
{
@@ -2496,8 +2500,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
// be nice and assert when we know the vulkan device would die a horrible death due to non-aligned reads
Q_ASSERT(aligned(bufInfo.offset, ubufAlign) == bufInfo.offset);
+ bufferInfoIndex = bufferInfos.count();
bufferInfos.append(bufInfo);
- writeInfo.pBufferInfo = &bufferInfos.last();
}
break;
case QRhiShaderResourceBinding::SampledTexture:
@@ -2513,8 +2517,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo.sampler = samplerD->sampler;
imageInfo.imageView = texD->imageView;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo);
- writeInfo.pImageInfo = &imageInfos.last();
}
break;
case QRhiShaderResourceBinding::ImageLoad:
@@ -2531,8 +2535,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
imageInfo.sampler = VK_NULL_HANDLE;
imageInfo.imageView = view;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+ imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo);
- writeInfo.pImageInfo = &imageInfos.last();
}
}
break;
@@ -2548,8 +2552,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
bufInfo.buffer = bufD->m_type == QRhiBuffer::Dynamic ? bufD->buffers[frameSlot] : bufD->buffers[0];
bufInfo.offset = VkDeviceSize(b->u.ubuf.offset);
bufInfo.range = VkDeviceSize(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size);
+ bufferInfoIndex = bufferInfos.count();
bufferInfos.append(bufInfo);
- writeInfo.pBufferInfo = &bufferInfos.last();
}
break;
default:
@@ -2557,10 +2561,20 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
}
writeInfos.append(writeInfo);
+ infoIndices.append({ bufferInfoIndex, imageInfoIndex });
}
++frameSlot;
}
+ for (int i = 0, writeInfoCount = writeInfos.count(); i < writeInfoCount; ++i) {
+ const int bufferInfoIndex = infoIndices[i].first;
+ const int imageInfoIndex = infoIndices[i].second;
+ if (bufferInfoIndex >= 0)
+ writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex];
+ else if (imageInfoIndex >= 0)
+ writeInfos[i].pImageInfo = &imageInfos[imageInfoIndex];
+ }
+
df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr);
}
@@ -4046,9 +4060,9 @@ QRhiTexture *QRhiVulkan::createTexture(QRhiTexture::Format format, const QSize &
QRhiSampler *QRhiVulkan::createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler::AddressMode u, QRhiSampler::AddressMode v)
+ QRhiSampler::AddressMode u, QRhiSampler::AddressMode v, QRhiSampler::AddressMode w)
{
- return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v);
+ return new QVkSampler(this, magFilter, minFilter, mipmapMode, u, v, w);
}
QRhiTextureRenderTarget *QRhiVulkan::createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
@@ -5543,8 +5557,8 @@ VkImageView QVkTexture::imageViewForLevel(int level)
}
QVkSampler::QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v)
- : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v)
+ AddressMode u, AddressMode v, AddressMode w)
+ : QRhiSampler(rhi, magFilter, minFilter, mipmapMode, u, v, w)
{
}
@@ -6208,6 +6222,11 @@ bool QVkGraphicsPipeline::build()
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
+ if (m_depthBias != 0 || !qFuzzyIsNull(m_slopeScaledDepthBias)) {
+ rastInfo.depthBiasEnable = true;
+ rastInfo.depthBiasConstantFactor = float(m_depthBias);
+ rastInfo.depthBiasSlopeFactor = m_slopeScaledDepthBias;
+ }
rastInfo.lineWidth = rhiD->hasWideLines ? m_lineWidth : 1.0f;
pipelineInfo.pRasterizationState = &rastInfo;
diff --git a/src/gui/rhi/qrhivulkan_p_p.h b/src/gui/rhi/qrhivulkan_p_p.h
index b0e90dae56..d42b83b882 100644
--- a/src/gui/rhi/qrhivulkan_p_p.h
+++ b/src/gui/rhi/qrhivulkan_p_p.h
@@ -154,7 +154,7 @@ struct QVkTexture : public QRhiTexture
struct QVkSampler : public QRhiSampler
{
QVkSampler(QRhiImplementation *rhi, Filter magFilter, Filter minFilter, Filter mipmapMode,
- AddressMode u, AddressMode v);
+ AddressMode u, AddressMode v, AddressMode w);
~QVkSampler();
void release() override;
bool build() override;
@@ -657,9 +657,12 @@ public:
const QSize &pixelSize,
int sampleCount,
QRhiTexture::Flags flags) override;
- QRhiSampler *createSampler(QRhiSampler::Filter magFilter, QRhiSampler::Filter minFilter,
+ QRhiSampler *createSampler(QRhiSampler::Filter magFilter,
+ QRhiSampler::Filter minFilter,
QRhiSampler::Filter mipmapMode,
- QRhiSampler:: AddressMode u, QRhiSampler::AddressMode v) override;
+ QRhiSampler:: AddressMode u,
+ QRhiSampler::AddressMode v,
+ QRhiSampler::AddressMode w) override;
QRhiTextureRenderTarget *createTextureRenderTarget(const QRhiTextureRenderTargetDescription &desc,
QRhiTextureRenderTarget::Flags flags) override;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 0024f070ea..ac39a8cf69 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1762,7 +1762,10 @@ int QTextEngine::shapeTextWithHarfbuzzNG(const QScriptItem &si,
}
#endif
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
if (!actualFontEngine->supportsSubPixelPositions() || (actualFontEngine->fontDef.styleStrategy & QFont::ForceIntegerMetrics)) {
+QT_WARNING_POP
for (uint i = 0; i < num_glyphs; ++i)
g.advances[i] = g.advances[i].round();
}
diff --git a/src/gui/text/qtextmarkdownimporter.cpp b/src/gui/text/qtextmarkdownimporter.cpp
index 88965046ce..7e18a10895 100644
--- a/src/gui/text/qtextmarkdownimporter.cpp
+++ b/src/gui/text/qtextmarkdownimporter.cpp
@@ -397,10 +397,12 @@ int QTextMarkdownImporter::cbEnterSpan(int spanType, void *det)
break;
case MD_SPAN_A: {
MD_SPAN_A_DETAIL *detail = static_cast<MD_SPAN_A_DETAIL *>(det);
- QString url = QString::fromLatin1(detail->href.text, int(detail->href.size));
- QString title = QString::fromLatin1(detail->title.text, int(detail->title.size));
+ QString url = QString::fromUtf8(detail->href.text, int(detail->href.size));
+ QString title = QString::fromUtf8(detail->title.text, int(detail->title.size));
+ charFmt.setAnchor(true);
charFmt.setAnchorHref(url);
- charFmt.setAnchorNames(QStringList(title));
+ if (!title.isEmpty())
+ charFmt.setToolTip(title);
charFmt.setForeground(m_palette.link());
qCDebug(lcMD) << "anchor" << url << title;
} break;
diff --git a/src/gui/text/qtextmarkdownwriter.cpp b/src/gui/text/qtextmarkdownwriter.cpp
index c9a63920c3..7bd321becc 100644
--- a/src/gui/text/qtextmarkdownwriter.cpp
+++ b/src/gui/text/qtextmarkdownwriter.cpp
@@ -56,10 +56,13 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcMDW, "qt.text.markdown.writer")
static const QChar Space = QLatin1Char(' ');
+static const QChar Tab = QLatin1Char('\t');
static const QChar Newline = QLatin1Char('\n');
+static const QChar CarriageReturn = QLatin1Char('\r');
static const QChar LineBreak = QChar(0x2028);
static const QChar DoubleQuote = QLatin1Char('"');
static const QChar Backtick = QLatin1Char('`');
+static const QChar Backslash = QLatin1Char('\\');
static const QChar Period = QLatin1Char('.');
QTextMarkdownWriter::QTextMarkdownWriter(QTextStream &stream, QTextDocument::MarkdownFeatures features)
@@ -291,6 +294,72 @@ static void maybeEscapeFirstChar(QString &s)
}
}
+struct LineEndPositions {
+ const QChar *lineEnd;
+ const QChar *nextLineBegin;
+};
+
+static LineEndPositions findLineEnd(const QChar *begin, const QChar *end)
+{
+ LineEndPositions result{ end, end };
+
+ while (begin < end) {
+ if (*begin == Newline) {
+ result.lineEnd = begin;
+ result.nextLineBegin = begin + 1;
+ break;
+ } else if (*begin == CarriageReturn) {
+ result.lineEnd = begin;
+ result.nextLineBegin = begin + 1;
+ if (((begin + 1) < end) && begin[1] == Newline)
+ ++result.nextLineBegin;
+ break;
+ }
+
+ ++begin;
+ }
+
+ return result;
+}
+
+static bool isBlankLine(const QChar *begin, const QChar *end)
+{
+ while (begin < end) {
+ if (*begin != Space && *begin != Tab)
+ return false;
+ ++begin;
+ }
+ return true;
+}
+
+static QString createLinkTitle(const QString &title)
+{
+ QString result;
+ result.reserve(title.size() + 2);
+ result += DoubleQuote;
+
+ const QChar *data = title.data();
+ const QChar *end = data + title.size();
+
+ while (data < end) {
+ const auto lineEndPositions = findLineEnd(data, end);
+
+ if (!isBlankLine(data, lineEndPositions.lineEnd)) {
+ while (data < lineEndPositions.nextLineBegin) {
+ if (*data == DoubleQuote)
+ result += Backslash;
+ result += *data;
+ ++data;
+ }
+ }
+
+ data = lineEndPositions.nextLineBegin;
+ }
+
+ result += DoubleQuote;
+ return result;
+}
+
int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ignoreFormat, bool ignoreEmpty)
{
if (block.text().isEmpty() && ignoreEmpty)
@@ -445,7 +514,12 @@ int QTextMarkdownWriter::writeBlock(const QTextBlock &block, bool wrap, bool ign
col += s.length();
} else if (fmt.hasProperty(QTextFormat::AnchorHref)) {
QString s = QLatin1Char('[') + fragmentText + QLatin1String("](") +
- fmt.property(QTextFormat::AnchorHref).toString() + QLatin1Char(')');
+ fmt.property(QTextFormat::AnchorHref).toString();
+ if (fmt.hasProperty(QTextFormat::TextToolTip)) {
+ s += Space;
+ s += createLinkTitle(fmt.property(QTextFormat::TextToolTip).toString());
+ }
+ s += QLatin1Char(')');
if (wrap && col + s.length() > ColumnLimit) {
m_stream << Newline << wrapIndentString;
col = m_wrappedLineIndent;