Merge remote-tracking branch 'origin/5.15' into dev

Change-Id: I99ee6f8b4bdc372437ee60d1feab931487fe55c4
This commit is contained in:
Lars Knoll 2020-03-04 09:54:35 +01:00 committed by Shawn Rutledge
commit 2a4b957789
111 changed files with 1066 additions and 568 deletions

View File

@ -32,84 +32,103 @@ manifestmeta.filters = highlighted android thumbnail ios
manifestmeta.highlighted.attributes = isHighlighted:true
manifestmeta.android.names = "QtQuick/Qt Quick Demo - Calqlatr" \
"QtWidgets/Application Chooser Example" \
"QtWidgets/Stickman Example" \
"QtWidgets/Move Blocks Example" \
"QtWidgets/Border Layout Example" \
"QtWidgets/Flow Layout Example" \
"QtWidgets/Dock Widgets Example" \
"QtWidgets/Recent Files Example" \
"QtWidgets/Concentric Circles Example" \
"QtWidgets/Gradients" \
"QtWidgets/Font Sampler Example" \
"QtWidgets/Path Stroking" \
"QtWidgets/Transformations Example" \
"QtWidgets/Syntax Highlighter Example" \
"QtWidgets/Calendar Example" \
"QtWidgets/Analog Clock Example" \
"QtWidgets/Calculator Example" \
"QtWidgets/Mouse Button Tester" \
"QtWidgets/Character Map Example" \
"QtWidgets/Digital Clock Example" \
"QtWidgets/Elided Label Example" \
"QtWidgets/Sliders Example" \
"QtWidgets/Tetrix Example" \
"QtWidgets/Group Box Example" \
"QtWidgets/Undo Framework" \
"QtWidgets/Colliding Mice Example" \
"QtWidgets/Diagram Scene Example" \
"QtWidgets/Elastic Nodes Example" \
"QtWidgets/Weather Anchor Layout Example" \
"QtNetwork/Torrent Example" \
"QtNetwork/Network Chat Example" \
"QtSQL/Master Detail Example" \
"QtLinguist/Arrow Pad Example" \
"QtGui/Raster Window Example" \
"QtGui/Analog Clock Window Example" \
"QtAndroidExtras/Qt Notifier" \
"QtMultimedia/QML Video Shader Effects Example" \
"QtMultimedia/QML Video Example" \
"QtMultimedia/QML Camera Example" \
"QtSVG/Text Object Example" \
"QtQML/Qt Quick Examples - XMLHttpRequest" \
"QtQuick/Qt Quick Particles Examples - *" \
"QtQuick/Qt Quick Examples - Touch Interaction" \
"QtQuick/Scene Graph - Custom Geometry" \
"QtQuick/Scene Graph - Graph" \
"QtQuick/Scene Graph - OpenGL Under QML" \
"QtQuick/Scene Graph - Painted Item" \
"QtQuick/Scene Graph - Rendering FBOs" \
"QtQuick/Scene Graph - Simple Material" \
"QtQuick/Qt Quick Examples - Image Elements" \
"QtQuick/Qt Quick Examples - Key Interaction" \
"QtQuick/Qt Quick Examples - Text" \
"QtQuick/Qt Quick Examples - Animation" \
"QtQuick/Qt Quick Examples - Shader Effects" \
"QtQuick/Qt Quick Examples - Canvas" \
"QtQuick/Qt Quick Examples - MouseArea" \
"QtQuick/Qt Quick Examples - Positioners" \
"QtQuick/Qt Quick Examples - Right to Left" \
"QtWidgets/Interview" \
"QtWidgets/Spreadsheet" \
"QtWidgets/Pixelator Example" \
"QtWidgets/Animated Tiles Example" \
"QtWidgets/Affine Transformations" \
"QtWidgets/Image Composition Example" \
"QtWidgets/Basic Drawing Example" \
"QtWidgets/Vector Deformation" \
"QtWidgets/Painter Paths Example" \
"QtWidgets/Style Sheet Example" \
"QtWidgets/Code Editor Example" \
"QtWidgets/Scribble Example" \
"QtWidgets/Line Edits Example" \
"QtWidgets/Calendar Widget Example" \
"QtWidgets/Completer Example" \
"QtWidgets/I18N Example" \
"QtQML/Extending QML - Grouped Properties Example" \
"QtQML/Extending QML - Methods Example" \
"QtQML/Extending QML - Signal Support Example" \
"QtQML/Extending QML - Attached Properties Example"
manifestmeta.android.names = "Qt3D/Qt 3D: Basic Shapes C++ Example" \
"Qt3D/Qt 3D: Planets QML Example" \
"Qt3D/Qt 3D: Simple Custom Material QML Example" \
"QtAndroidExtras/Qt Notifier" \
"QtBluetooth/Bluetooth Low Energy Scanner Example" \
"QtBluetooth/Bluetooth Scanner Example" \
"QtBluetooth/QML Bluetooth Scanner Example" \
"QtCharts/*" \
"QtConcurrent/QtConcurrent Progress Dialog Example" \
"QtDataVisualization/Audiolevels Example" \
"QtDataVisualization/Qt Quick 2 Scatter Example" \
"QtDataVisualization/Qt Quick 2 Surface Multiseries Example" \
"QtGui/Analog Clock Window Example" \
"QtGui/OpenGL Window Example" \
"QtGui/Raster Window Example" \
"QtLinguist/Arrow Pad Example" \
"QtLinguistManual/Hello tr() Example" \
"QtLocation/Map Viewer (QML)" \
"QtLocation/Places Map (QML)" \
"QtLocation/Plane Spotter (QML)" \
"QtMultimedia/AudioEngine Example" \
"QtMultimedia/Camera Example" \
"QtMultimedia/QML Camera Example" \
"QtMultimedia/QML Video Example" \
"QtMultimedia/QML Video Shader Effects Example" \
"QtNFC/Annotated URL Example" \
"QtNFC/QML Poster Example" \
"QtOpenGL/2D Painting Example" \
"QtOpenGL/Hello GLES3 Example" \
"QtOpenGL/Textures Example" \
"QtPositioning/SatelliteInfo (C++/QML)" \
"QtPositioning/Weather Info (C++/QML)" \
"QtPurchasing/Qt Purchasing Examples - QtHangman" \
"QtQML/Extending QML - Attached Properties Example" \
"QtQML/Extending QML - Grouped Properties Example" \
"QtQML/Extending QML - Methods Example" \
"QtQML/Extending QML - Signal Support Example" \
"QtQML/Qt Quick Examples - XMLHttpRequest" \
"QtQml/Qt Quick Examples - XMLHttpRequest" \
"QtQuick/*" \
"QtQuickControls/*" \
"QtQuickControls1/Qt Quick Controls 1 - Calendar Example" \
"QtQuickControls1/Qt Quick Controls 1 - Gallery" \
"QtQuickControls1/Qt Quick Controls 1 - Styles Example" \
"QtQuickControls1/Qt Quick Controls 1 - Table View Example" \
"QtQuickControls1/Qt Quick Controls 1 - Touch Gallery" \
"QtQuickDialogs/*" \
"QtQuickExtras/*" \
"QtSCXML/Qt SCXML Calculator QML Example" \
"QtSCXML/Qt SCXML Sudoku Example" \
"QtSCXML/Qt SCXML Traffic Light Example (Dynamic)" \
"QtSCXML/Qt SCXML Traffic Light QML Example (Dynamic)" \
"QtSQL/Master Detail Example" \
"QtSVG/Text Object Example" \
"QtUiTools/Text Finder Example" \
"QtWebView/Qt WebView Examples - Minibrowser" \
"QtWidgets/Address Book Example" \
"QtWidgets/Affine Transformations" \
"QtWidgets/Analog Clock Example" \
"QtWidgets/Animated Tiles Example" \
"QtWidgets/Application Chooser Example" \
"QtWidgets/Basic Layouts Example" \
"QtWidgets/Border Layout Example" \
"QtWidgets/Code Editor Example" \
"QtWidgets/Colliding Mice Example" \
"QtWidgets/Concentric Circles Example" \
"QtWidgets/Digital Clock Example" \
"QtWidgets/Dynamic Layouts Example" \
"QtWidgets/Easing Curves Example" \
"QtWidgets/Editable Tree Model Example" \
"QtWidgets/Elided Label Example" \
"QtWidgets/Event Transitions Example" \
"QtWidgets/Fade Message Effect Example" \
"QtWidgets/Flow Layout Example" \
"QtWidgets/Font Sampler Example" \
"QtWidgets/Frozen Column Example" \
"QtWidgets/Gradients" \
"QtWidgets/Group Box Example" \
"QtWidgets/Image Composition Example" \
"QtWidgets/Line Edits Example" \
"QtWidgets/Mouse Button Tester" \
"QtWidgets/Move Blocks Example" \
"QtWidgets/Painter Paths Example" \
"QtWidgets/Painter Paths Example" \
"QtWidgets/Path Stroking" \
"QtWidgets/Pixelator Example" \
"QtWidgets/Recent Files Example" \
"QtWidgets/SDI Example" \
"QtWidgets/Scribble Example" \
"QtWidgets/Simple Tree Model Example" \
"QtWidgets/Sliders Example" \
"QtWidgets/Spreadsheet" \
"QtWidgets/Touch Dials Example" \
"QtWidgets/Transformations Example" \
"QtWidgets/Undo Framework" \
"QtWidgets/Vector Deformation" \
"QtWidgets/Wiggly Example"
manifestmeta.android.tags = android

View File

@ -81,7 +81,11 @@ int main(int argc, char *argv[])
const QRect availableSize = httpWin.screen()->availableGeometry();
httpWin.resize(availableSize.width() / 5, availableSize.height() / 5);
httpWin.move((availableSize.width() - httpWin.width()) / 2, (availableSize.height() - httpWin.height()) / 2);
#ifdef Q_OS_ANDROID
httpWin.showMaximized();
#else
httpWin.show();
#endif
return app.exec();
}

View File

@ -58,6 +58,9 @@ static constexpr int MouseCount = 7;
//! [0]
int main(int argc, char **argv)
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
//! [0]

View File

@ -55,6 +55,9 @@
int main(int argv, char *args[])
{
Q_INIT_RESOURCE(diagramscene);
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argv, args);
MainWindow mainWindow;

View File

@ -55,6 +55,9 @@
//! [0]
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
MainWindow mw;
mw.show();

View File

@ -56,6 +56,10 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(spreadsheet);
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
SpreadSheet sheet(10, 6);
sheet.setWindowIcon(QPixmap(":/images/interview.png"));

View File

@ -56,7 +56,11 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
#ifdef Q_OS_ANDROID
dialog.showMaximized();
#else
dialog.show();
#endif
return app.exec();
}

View File

@ -56,6 +56,11 @@ int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Dialog dialog;
#ifdef Q_OS_ANDROID
dialog.showMaximized();
#else
dialog.show();
#endif
return app.exec();
}

View File

@ -58,6 +58,9 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(application);
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
QCoreApplication::setOrganizationName("QtProject");

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
Q_INIT_RESOURCE(dockwidgets);
MainWindow mainWin;

View File

@ -55,7 +55,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(affine);
#ifdef Q_OS_ANDROID
qputenv("QT_SCALE_FACTOR", "2");
#endif
QApplication app(argc, argv);
XFormWidget xformWidget(nullptr);

View File

@ -787,8 +787,8 @@ XFormWidget::XFormWidget(QWidget *parent)
view = new XFormView(this);
view->setMinimumSize(200, 200);
QGroupBox *mainGroup = new QGroupBox(this);
mainGroup->setFixedWidth(180);
QWidget *mainContentWidget = new QWidget();
QGroupBox *mainGroup = new QGroupBox(mainContentWidget);
mainGroup->setTitle(tr("Affine Transformations"));
QGroupBox *rotateGroup = new QGroupBox(mainGroup);
@ -837,10 +837,6 @@ XFormWidget::XFormWidget(QWidget *parent)
whatsThisButton->setText(tr("What's This?"));
whatsThisButton->setCheckable(true);
QHBoxLayout *viewLayout = new QHBoxLayout(this);
viewLayout->addWidget(view);
viewLayout->addWidget(mainGroup);
QVBoxLayout *rotateGroupLayout = new QVBoxLayout(rotateGroup);
rotateGroupLayout->addWidget(rotateSlider);
@ -871,6 +867,20 @@ XFormWidget::XFormWidget(QWidget *parent)
#endif
mainGroupLayout->addWidget(whatsThisButton);
mainGroup->setLayout(mainGroupLayout);
QVBoxLayout *mainContentLayout = new QVBoxLayout();
mainContentLayout->addWidget(mainGroup);
mainContentWidget->setLayout(mainContentLayout);
QScrollArea *mainScrollArea = new QScrollArea();
mainScrollArea->setWidget(mainContentWidget);
mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
QHBoxLayout *viewLayout = new QHBoxLayout(this);
viewLayout->addWidget(view);
viewLayout->addWidget(mainScrollArea);
connect(rotateSlider, &QSlider::valueChanged, view, &XFormView::changeRotation);
connect(shearSlider, &QSlider::valueChanged, view, &XFormView::changeShear);
connect(scaleSlider, &QSlider::valueChanged, view, &XFormView::changeScale);

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
Window window;
window.show();

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
MainWindow window;
window.show();

View File

@ -282,7 +282,8 @@ GradientWidget::GradientWidget(QWidget *parent)
m_renderer = new GradientRenderer(this);
QGroupBox *mainGroup = new QGroupBox(this);
QWidget *mainContentWidget = new QWidget();
QGroupBox *mainGroup = new QGroupBox(mainContentWidget);
mainGroup->setTitle(tr("Gradients"));
QGroupBox *editorGroup = new QGroupBox(mainGroup);
@ -327,11 +328,6 @@ GradientWidget::GradientWidget(QWidget *parent)
whatsThisButton->setText(tr("What's This?"));
whatsThisButton->setCheckable(true);
// Layouts
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(m_renderer);
mainLayout->addWidget(mainGroup);
mainGroup->setFixedWidth(200);
QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
mainGroupLayout->addWidget(editorGroup);
@ -370,6 +366,21 @@ GradientWidget::GradientWidget(QWidget *parent)
defaultsGroupLayout->addWidget(default3Button);
editorGroupLayout->addWidget(default4Button);
mainGroup->setLayout(mainGroupLayout);
QVBoxLayout *mainContentLayout = new QVBoxLayout();
mainContentLayout->addWidget(mainGroup);
mainContentWidget->setLayout(mainContentLayout);
QScrollArea *mainScrollArea = new QScrollArea();
mainScrollArea->setWidget(mainContentWidget);
mainScrollArea->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
// Layouts
QHBoxLayout *mainLayout = new QHBoxLayout(this);
mainLayout->addWidget(m_renderer);
mainLayout->addWidget(mainScrollArea);
connect(m_editor, &GradientEditor::gradientStopsChanged,
m_renderer, &GradientRenderer::setGradientStops);
connect(m_linearButton, &QRadioButton::clicked,

View File

@ -55,6 +55,9 @@
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(gradients);
#ifdef Q_OS_ANDROID
qputenv("QT_SCALE_FACTOR", "2");
#endif
QApplication app(argc, argv);

View File

@ -55,6 +55,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(pathstroke);
#ifdef Q_OS_ANDROID
qputenv("QT_SCALE_FACTOR", "2");
#endif
QApplication app(argc, argv);

View File

@ -54,6 +54,9 @@
int main(int argc, char **argv)
{
Q_INIT_RESOURCE(undo);
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
Calculator calc;
calc.show();

View File

@ -55,6 +55,9 @@
//! [0]
int main( int argc, char *argv[] )
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication application( argc, argv );
TestWidget w;
w.showFullScreen();

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
MainWindow window;
window.show();

View File

@ -54,6 +54,9 @@
int main(int argc, char *argv[])
{
#ifdef Q_OS_ANDROID
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QApplication app(argc, argv);
Window window;
window.show();

View File

@ -131,7 +131,7 @@ void RSSListing::get(const QUrl &url)
currentReply = manager.get(request);
connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged()));
connect(currentReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
connect(currentReply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError)));
}
/*

View File

@ -20,11 +20,11 @@ qtConfig(c++1z): CONFIG += c++1z
qtConfig(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11
qtConfig(separate_debug_info): CONFIG += separate_debug_info
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
contains(TEMPLATE, .*lib) {
# module and plugins
unix:qtConfig(reduce_relocations): CONFIG += bsymbolic_functions
qtConfig(separate_debug_info): CONFIG += separate_debug_info
!isEmpty(_QMAKE_SUPER_CACHE_): \
rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*

View File

@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.15
\fn qfloat16::copySign(qfloat16 sign) const noexcept
\fn qfloat16 qfloat16::copySign(qfloat16 sign) const noexcept
Returns a qfloat16 with the sign of \a sign but the rest of its value taken
from this qfloat16. Serves as qfloat16's equivalent of std::copysign().

View File

@ -884,7 +884,11 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
return;
}
#endif
doUnregisterEventNotifier(notifier);
}
void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier)
{
Q_D(QEventDispatcherWin32);
int i = d->winEventNotifierList.indexOf(notifier);
@ -996,6 +1000,10 @@ void QEventDispatcherWin32::closingDown()
doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj);
Q_ASSERT(d->active_fd.isEmpty());
// clean up any eventnotifiers
while (!d->winEventNotifierList.isEmpty())
doUnregisterEventNotifier(d->winEventNotifierList.first());
// clean up any timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->unregisterTimer(d->timerVec.at(i));

View File

@ -110,6 +110,7 @@ protected:
QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
virtual void sendPostedEvents();
void doUnregisterSocketNotifier(QSocketNotifier *notifier);
void doUnregisterEventNotifier(QWinEventNotifier *notifier);
private:
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);

View File

@ -198,11 +198,8 @@ void QWinEventNotifier::setEnabled(bool enable)
d->enabled = enable;
QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
if (!eventDispatcher) { // perhaps application is shutting down
if (!enable && d->waitHandle != nullptr)
d->unregisterWaitObject();
if (!eventDispatcher) // perhaps application is shutting down
return;
}
if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
return;

View File

@ -664,7 +664,15 @@ QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnu
load(data, size);
}
#endif
#else // !QT_CONFIG(mimetype_database)
// never called in release mode, but some debug builds may need
// this to be defined.
QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
: QMimeProviderBase(db, QString())
{
Q_UNREACHABLE();
}
#endif // QT_CONFIG(mimetype_database)
QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
: QMimeProviderBase(db, directory)

View File

@ -135,13 +135,10 @@ public:
enum InternalDatabaseEnum { InternalDatabase };
#if QT_CONFIG(mimetype_database)
enum : bool { InternalDatabaseAvailable = true };
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
#else
enum : bool { InternalDatabaseAvailable = false };
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum)
: QMimeProviderBase(db, QString())
{ Q_UNREACHABLE(); };
#endif
QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnum);
QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory);
~QMimeXMLProvider();

View File

@ -7626,7 +7626,10 @@ static ResultList splitString(const StringSource &source, const QChar *sep,
#if QT_DEPRECATED_SINCE(5, 15)
Qt::SplitBehavior mapSplitBehavior(QString::SplitBehavior sb)
{
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
return sb & QString::SkipEmptyParts ? Qt::SkipEmptyParts : Qt::KeepEmptyParts;
QT_WARNING_POP
}
#endif

View File

@ -1383,6 +1383,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
\note If localized month and day names are desired, please switch to using
QLocale::system().toString() as QDate methods shall change to use English (C
locale) names at Qt 6.
\sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
@ -1884,6 +1888,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 3
\note If localized month and day names are used, please switch to using
QLocale::system().toDate() as QDate methods shall change to only recognize
English (C locale) names at Qt 6.
\sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate()
*/
@ -2244,6 +2252,10 @@ QT_WARNING_POP
If the time is invalid, an empty string will be returned.
If \a format is empty, the default format "hh:mm:ss" is used.
\note If localized forms of am or pm (the AP, ap, A or a formats) are
desired, please switch to using QLocale::system().toString() as QTime
methods shall change to use English (C locale) at Qt 6.
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
QString QTime::toString(QStringView format) const
@ -2641,6 +2653,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 8
\note If localized forms of am or pm (the AP, ap, A or a formats) are used,
please switch to using QLocale::system().toTime() as QTime methods shall
change to only recognize English (C locale) at Qt 6.
\sa toString(), QDateTime::fromString(), QDate::fromString(),
QLocale::toTime()
*/
@ -4541,6 +4557,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned.
\note If localized month and day names are desired, please switch to using
QLocale::system().toString() as QDateTime methods shall change to use
English (C locale) names at Qt 6.
\sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/
QString QDateTime::toString(QStringView format) const
@ -5580,6 +5600,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 14
\note If localized month and day names are used, please switch to using
QLocale::system().toDateTime() as QDateTime methods shall change to only
recognize English (C locale) names at Qt 6.
\sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime()
*/

View File

@ -1574,7 +1574,6 @@ uint qHash(long double key, uint seed) noexcept
*/
/*! \fn template <class Key, class T> int QHash<Key, T>::count(const Key &key) const
\obsolete
Returns the number of items associated with the \a key.
@ -2693,13 +2692,6 @@ uint qHash(long double key, uint seed) noexcept
\sa QHash::remove()
*/
/*! \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key) const
Returns the number of items associated with the \a key.
\sa contains(), insert()
*/
/*!
\fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3

View File

@ -309,10 +309,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const;
QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<Key> uniqueKeys() const;
QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
int count(const Key &key) const;
class const_iterator;
@ -512,8 +512,8 @@ public:
iterator insert(const Key &key, const T &value);
void insert(const QHash &hash);
#if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
QT_DEPRECATED_VERSION_X_5_15("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other);
#endif
// STL compatibility
@ -710,6 +710,19 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
return res;
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
{
int cnt = 0;
Node *node = *findNode(akey);
if (node != e) {
do {
++cnt;
} while ((node = node->next) != e && node->key == akey);
}
return cnt;
}
template <class Key, class T>
Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const
{
@ -1053,7 +1066,6 @@ public:
int remove(const Key &key, const T &value);
int count(const Key &key) const;
int count(const Key &key, const T &value) const;
QList<Key> uniqueKeys() const;
@ -1206,12 +1218,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values(const Key &akey) const
return static_cast<const QMultiHash<Key, T> *>(this)->values(akey);
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE int QHash<Key, T>::count(const Key &akey) const
{
return static_cast<const QMultiHash<Key, T> *>(this)->count(akey);
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const
{
@ -1232,19 +1238,6 @@ Q_OUTOFLINE_TEMPLATE QList<T> QMultiHash<Key, T>::values(const Key &akey) const
return res;
}
template <class Key, class T>
Q_OUTOFLINE_TEMPLATE int QMultiHash<Key, T>::count(const Key &akey) const
{
int cnt = 0;
Node *node = *findNode(akey);
if (node != this->e) {
do {
++cnt;
} while ((node = node->next) != this->e && node->key == akey);
}
return cnt;
}
#if !defined(QT_NO_JAVA_STYLE_ITERATORS)
template <class Key, class T>
class QHashIterator

View File

@ -195,7 +195,6 @@ public:
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::difference_type difference_type;
typedef std::pair<Key, T> value_type;
typedef const value_type *pointer;
typedef const value_type &reference;
QKeyValueIterator() = default;
@ -206,6 +205,31 @@ public:
return std::pair<Key, T>(i.key(), i.value());
}
struct pointer {
pointer(value_type&& r_)
: r(std::move(r_))
{}
pointer() = default;
pointer(const pointer &other) = default;
pointer(pointer &&other) = default;
pointer& operator=(const pointer &other) = default;
pointer& operator=(pointer &&other) = default;
value_type& operator*() const {
return r;
}
value_type r;
const value_type *operator->() const {
return &r;
}
};
pointer operator->() const {
return pointer(std::pair<Key, T>(i.key(), i.value()));
}
friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i == rhs.i; }
friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) noexcept { return lhs.i != rhs.i; }

View File

@ -57,7 +57,7 @@
\internal
*/
/*! \typedef QKeyValueIterator::pointer
/*! \struct QKeyValueIterator::pointer
\internal
*/
@ -75,11 +75,20 @@
Constructs a QKeyValueIterator on top of \a o.
*/
/*! \fn template<typename Key, typename T, class Iterator> const T &QKeyValueIterator<Key, T, Iterator>::operator*() const
/*! \fn template<typename Key, typename T, class Iterator> std::pair<Key, T> QKeyValueIterator<Key, T, Iterator>::operator*() const
Returns the current entry as a pair.
*/
/*! \fn template<typename Key, typename T, class Iterator> pointer QKeyValueIterator<Key, T, Iterator>::operator->() const
Returns the current entry as a pointer-like object to the pair.
\since 5.15
\sa operator*()
*/
/*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
\relates QKeyValueIterator

View File

@ -814,11 +814,10 @@ void QMapDataBase::freeData(QMapDataBase *d)
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count(const Key &key) const
\obsolete
Returns the number of items associated with key \a key.
\sa QMultiMap::count()
\sa contains(), QMultiMap::count()
*/
/*! \fn template <class Key, class T> int QMap<Key, T>::count() const
@ -2115,11 +2114,6 @@ void QMapDataBase::freeData(QMapDataBase *d)
inserted one.
*/
/*! \fn template <class Key, class T> int QMultiMap<Key, T>::count(const Key &key) const
Returns the number of items associated with key \a key.
*/
/*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
\since 4.2

View File

@ -373,10 +373,10 @@ public:
QList<Key> keys(const T &value) const;
QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") int count(const Key &key) const;
QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<Key> uniqueKeys() const;
QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QList<T> values(const Key &key) const;
#endif
int count(const Key &key) const;
inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
@ -559,9 +559,9 @@ public:
iterator insert(const_iterator pos, const Key &key, const T &value);
void insert(const QMap<Key, T> &map);
#if QT_DEPRECATED_SINCE(5, 15)
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
QT_DEPRECATED_X("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value);
QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") iterator insertMulti(const_iterator pos, const Key &akey, const T &avalue);
QT_DEPRECATED_VERSION_X_5_15("Use QMultiMap for maps storing multiple values with the same key.") QMap<Key, T> &unite(const QMap<Key, T> &other);
#endif
// STL compatibility
@ -654,6 +654,23 @@ Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
return n->value;
}
template <class Key, class T>
Q_INLINE_TEMPLATE int QMap<Key, T>::count(const Key &akey) const
{
Node *firstNode;
Node *lastNode;
d->nodeRange(akey, &firstNode, &lastNode);
const_iterator ci_first(firstNode);
const const_iterator ci_last(lastNode);
int cnt = 0;
while (ci_first != ci_last) {
++cnt;
++ci_first;
}
return cnt;
}
template <class Key, class T>
Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const
{
@ -1116,7 +1133,6 @@ public:
int remove(const Key &key, const T &value);
int count(const Key &key) const;
int count(const Key &key, const T &value) const;
typename QMap<Key, T>::iterator find(const Key &key, const T &value) {
@ -1289,23 +1305,6 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
return n;
}
template <class Key, class T>
Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &akey) const
{
QMultiMap::Node *firstNode;
QMultiMap::Node *lastNode;
this->d->nodeRange(akey, &firstNode, &lastNode);
typename QMap<Key, T>::const_iterator ci_first(firstNode);
const typename QMap<Key, T>::const_iterator ci_last(lastNode);
int cnt = 0;
while (ci_first != ci_last) {
++cnt;
++ci_first;
}
return cnt;
}
template <class Key, class T>
Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const
{
@ -1333,12 +1332,6 @@ QList<T> QMap<Key, T>::values(const Key &key) const
return static_cast<const QMultiMap<Key, T> *>(this)->values(key);
}
template<class Key, class T>
int QMap<Key, T>::count(const Key &key) const
{
return static_cast<const QMultiMap<Key, T> *>(this)->count(key);
}
template<class Key, class T>
typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value)
{

View File

@ -870,13 +870,6 @@ void QBmpHandler::setOption(ImageOption option, const QVariant &value)
Q_UNUSED(value);
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QBmpHandler::name() const
{
return formatName();
}
#endif
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_BMP

View File

@ -113,9 +113,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;

View File

@ -1296,13 +1296,6 @@ void QPngHandler::setOption(ImageOption option, const QVariant &value)
d->scaledSize = value.toSize();
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QPngHandler::name() const
{
return "png";
}
#endif
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_PNG

View File

@ -69,10 +69,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override;

View File

@ -576,13 +576,6 @@ void QPpmHandler::setOption(ImageOption option, const QVariant &value)
subType = value.toByteArray().toLower();
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QPpmHandler::name() const
{
return subType.isEmpty() ? QByteArray("ppm") : subType;
}
#endif
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_PPM

View File

@ -67,10 +67,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device, QByteArray *subType = nullptr);
QVariant option(ImageOption option) const override;

View File

@ -357,13 +357,6 @@ void QXbmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QXbmHandler::name() const
{
return "xbm";
}
#endif
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_XBM

View File

@ -66,10 +66,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;

View File

@ -1280,13 +1280,6 @@ void QXpmHandler::setOption(ImageOption option, const QVariant &value)
fileName = value.toString();
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QXpmHandler::name() const
{
return "xpm";
}
#endif
QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_XPM

View File

@ -68,10 +68,6 @@ public:
static bool canRead(QIODevice *device);
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override;

View File

@ -1731,7 +1731,7 @@ void QWindow::setGeometry(const QRect &rect)
if (newScreen && isTopLevel())
nativeRect = QHighDpi::toNativePixels(rect, newScreen);
else
nativeRect = QHighDpi::toNativePixels(rect, this);
nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
d->platformWindow->setGeometry(nativeRect);
} else {
d->geometry = rect;
@ -1782,8 +1782,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
QRect QWindow::geometry() const
{
Q_D(const QWindow);
if (d->platformWindow)
return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this);
if (d->platformWindow) {
const auto nativeGeometry = d->platformWindow->geometry();
return isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, this)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, this);
}
return d->geometry;
}

View File

@ -298,14 +298,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window)
, newGeometry(newGeometry)
{
if (const QPlatformWindow *pw = window->handle())
requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window);
if (const QPlatformWindow *pw = window->handle()) {
const auto nativeGeometry = pw->QPlatformWindow::geometry();
requestedGeometry = window->isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, window)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
}
}
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{
Q_ASSERT(window);
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window));
const auto newRectDi = window->isTopLevel()
? QHighDpi::fromNativePixels(newRect, window)
: QHighDpi::fromNativeLocalPosition(newRect, window);
auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect);

View File

@ -2048,11 +2048,9 @@ QRhiResource::Type QRhiBuffer::resourceType() const
UniformBuffer may not even be backed by a native buffer object at all if
uniform buffers are not used or supported by a given backend and graphics
API. There are also differences to how data is written to the buffer and
the type of backing memory used, and, if host visible memory is involved,
when memory writes become available and visible. Therefore, in general it
is recommended to limit native buffer object access to vertex and index
buffers with types Static or Immutable, because these operate in a
relatively uniform manner with all backends.
the type of backing memory used. For buffers backed by host visible memory,
calling this function guarantees that pending host writes are executed for
all the returned native buffers.
\sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
*/
@ -2341,6 +2339,31 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
return false;
}
/*!
With some graphics APIs, such as Vulkan, integrating custom rendering code
that uses the graphics API directly needs special care when it comes to
image layouts. This function allows communicating the expected layout the
image backing the QRhiTexture is in after the native rendering commands.
For example, consider rendering into a QRhiTexture's VkImage directly with
Vulkan in a code block enclosed by QRhiCommandBuffer::beginExternal() and
QRhiCommandBuffer::endExternal(), followed by using the image for texture
sampling in a QRhi-based render pass. To avoid potentially incorrect image
layout transitions, this function can be used to indicate what the image
layout will be once the commands recorded in said code block complete.
Calling this function makes sense only after
QRhiCommandBuffer::endExternal() and before a subsequent
QRhiCommandBuffer::beginPass().
This function has no effect with QRhi backends where the underlying
graphics API does not expose a concept of image layouts.
*/
void QRhiTexture::setNativeLayout(int layout)
{
Q_UNUSED(layout);
}
/*!
\class QRhiSampler
\internal

View File

@ -791,6 +791,7 @@ public:
virtual bool build() = 0;
virtual NativeTexture nativeTexture();
virtual bool buildFrom(NativeTexture src);
virtual void setNativeLayout(int layout);
protected:
QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_,

View File

@ -580,6 +580,11 @@ void QRhiD3D11::setGraphicsPipeline(QRhiCommandBuffer *cb, QRhiGraphicsPipeline
}
}
static const int RBM_SUPPORTED_STAGES = 3;
static const int RBM_VERTEX = 0;
static const int RBM_FRAGMENT = 1;
static const int RBM_COMPUTE = 2;
void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
@ -608,7 +613,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWrites(bufD);
if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
srbUpdate = true;
@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
}
}
if (srbUpdate)
updateShaderResourceBindings(srbD);
if (srbUpdate) {
const QShader::NativeResourceBindingMap *resBindMaps[RBM_SUPPORTED_STAGES];
memset(resBindMaps, 0, sizeof(resBindMaps));
if (gfxPsD) {
resBindMaps[RBM_VERTEX] = &gfxPsD->vs.nativeResourceBindingMap;
resBindMaps[RBM_FRAGMENT] = &gfxPsD->fs.nativeResourceBindingMap;
} else {
resBindMaps[RBM_COMPUTE] = &compPsD->cs.nativeResourceBindingMap;
}
updateShaderResourceBindings(srbD, resBindMaps);
}
const bool srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
@ -725,7 +739,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWrites(bufD);
if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
|| cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
@ -757,7 +771,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf);
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
if (ibufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(ibufD);
executeBufferHostWrites(ibufD);
const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
: DXGI_FORMAT_R32_UINT;
@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cbD->commands.append(cmd);
}
void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
static inline QPair<int, int> mapBinding(int binding,
int stageIndex,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
const QShader::NativeResourceBindingMap *map = nativeResourceBindingMaps[stageIndex];
if (!map || map->isEmpty())
return { binding, binding }; // old QShader versions do not have this map, assume 1:1 mapping then
auto it = map->constFind(binding);
if (it != map->cend())
return *it;
// Hitting this path is normal too. It is not given that the resource is
// present in the shaders for all the stages specified by the visibility
// mask in the QRhiShaderResourceBinding.
return { -1, -1 };
}
void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[])
{
srbD->vsubufs.clear();
srbD->vsubufoffsets.clear();
@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->csUAVs.clear();
struct Stage {
struct Buffer {
int breg; // b0, b1, ...
ID3D11Buffer *buffer;
uint offsetInConstants;
uint sizeInConstants;
};
struct Texture {
int treg; // t0, t1, ...
ID3D11ShaderResourceView *srv;
};
struct Sampler {
int sreg; // s0, s1, ...
ID3D11SamplerState *sampler;
};
struct Uav {
int ureg;
ID3D11UnorderedAccessView *uav;
};
QVarLengthArray<Buffer, 8> buffers;
QVarLengthArray<Texture, 8> textures;
QVarLengthArray<Sampler, 8> samplers;
QVarLengthArray<Uav, 8> uavs;
} res[RBM_SUPPORTED_STAGES];
for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// (ByteWidth) is always a multiple of 256.
const uint sizeInConstants = uint(aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vsubufs.feed(b->binding, bufD->buffer);
srbD->vsubufoffsets.feed(b->binding, offsetInConstants);
srbD->vsubufsizes.feed(b->binding, sizeInConstants);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fsubufs.feed(b->binding, bufD->buffer);
srbD->fsubufoffsets.feed(b->binding, offsetInConstants);
srbD->fsubufsizes.feed(b->binding, sizeInConstants);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
srbD->csubufs.feed(b->binding, bufD->buffer);
srbD->csubufoffsets.feed(b->binding, offsetInConstants);
srbD->csubufsizes.feed(b->binding, sizeInConstants);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0)
res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
}
}
break;
case QRhiShaderResourceBinding::SampledTexture:
{
// A sampler with binding N is mapped to a HLSL sampler and texture
// with registers sN and tN by SPIRV-Cross.
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texId = texD->m_id;
@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vssamplers.feed(b->binding, samplerD->samplerState);
srbD->vsshaderresources.feed(b->binding, texD->srv);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv });
res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fssamplers.feed(b->binding, samplerD->samplerState);
srbD->fsshaderresources.feed(b->binding, texD->srv);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv });
res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
srbD->cssamplers.feed(b->binding, samplerD->samplerState);
srbD->csshaderresources.feed(b->binding, texD->srv);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv });
res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
}
}
}
break;
@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
if (uav)
srbD->csUAVs.feed(b->binding, uav);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0) {
ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
if (uav)
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
}
} else {
qWarning("Unordered access only supported at compute stage");
}
@ -1882,9 +1950,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.sbuf.id = bufD->m_id;
bd.sbuf.generation = bufD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
if (uav)
srbD->csUAVs.feed(b->binding, uav);
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0) {
ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
if (uav)
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
}
} else {
qWarning("Unordered access only supported at compute stage");
}
@ -1896,31 +1967,79 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
}
}
// 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.
for (int stage = 0; stage < RBM_SUPPORTED_STAGES; ++stage) {
std::sort(res[stage].buffers.begin(), res[stage].buffers.end(), [](const Stage::Buffer &a, const Stage::Buffer &b) {
return a.breg < b.breg;
});
std::sort(res[stage].textures.begin(), res[stage].textures.end(), [](const Stage::Texture &a, const Stage::Texture &b) {
return a.treg < b.treg;
});
std::sort(res[stage].samplers.begin(), res[stage].samplers.end(), [](const Stage::Sampler &a, const Stage::Sampler &b) {
return a.sreg < b.sreg;
});
std::sort(res[stage].uavs.begin(), res[stage].uavs.end(), [](const Stage::Uav &a, const Stage::Uav &b) {
return a.ureg < b.ureg;
});
}
for (const Stage::Buffer &buf : qAsConst(res[RBM_VERTEX].buffers)) {
srbD->vsubufs.feed(buf.breg, buf.buffer);
srbD->vsubufoffsets.feed(buf.breg, buf.offsetInConstants);
srbD->vsubufsizes.feed(buf.breg, buf.sizeInConstants);
}
srbD->vsubufs.finish();
srbD->vsubufoffsets.finish();
srbD->vsubufsizes.finish();
for (const Stage::Buffer &buf : qAsConst(res[RBM_FRAGMENT].buffers)) {
srbD->fsubufs.feed(buf.breg, buf.buffer);
srbD->fsubufoffsets.feed(buf.breg, buf.offsetInConstants);
srbD->fsubufsizes.feed(buf.breg, buf.sizeInConstants);
}
srbD->fsubufs.finish();
srbD->fsubufoffsets.finish();
srbD->fsubufsizes.finish();
for (const Stage::Buffer &buf : qAsConst(res[RBM_COMPUTE].buffers)) {
srbD->csubufs.feed(buf.breg, buf.buffer);
srbD->csubufoffsets.feed(buf.breg, buf.offsetInConstants);
srbD->csubufsizes.feed(buf.breg, buf.sizeInConstants);
}
srbD->csubufs.finish();
srbD->csubufoffsets.finish();
srbD->csubufsizes.finish();
for (const Stage::Texture &t : qAsConst(res[RBM_VERTEX].textures))
srbD->vsshaderresources.feed(t.treg, t.srv);
for (const Stage::Sampler &s : qAsConst(res[RBM_VERTEX].samplers))
srbD->vssamplers.feed(s.sreg, s.sampler);
srbD->vssamplers.finish();
srbD->vsshaderresources.finish();
for (const Stage::Texture &t : qAsConst(res[RBM_FRAGMENT].textures))
srbD->fsshaderresources.feed(t.treg, t.srv);
for (const Stage::Sampler &s : qAsConst(res[RBM_FRAGMENT].samplers))
srbD->fssamplers.feed(s.sreg, s.sampler);
srbD->fssamplers.finish();
srbD->fsshaderresources.finish();
for (const Stage::Texture &t : qAsConst(res[RBM_COMPUTE].textures))
srbD->csshaderresources.feed(t.treg, t.srv);
for (const Stage::Sampler &s : qAsConst(res[RBM_COMPUTE].samplers))
srbD->cssamplers.feed(s.sreg, s.sampler);
srbD->cssamplers.finish();
srbD->csshaderresources.finish();
for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
srbD->csUAVs.feed(u.ureg, u.uav);
srbD->csUAVs.finish();
}
void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD)
void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
{
if (!bufD->hasPendingDynamicUpdates)
return;
@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
context->VSSetShader(psD->vs, nullptr, 0);
context->PSSetShader(psD->fs, nullptr, 0);
context->VSSetShader(psD->vs.shader, nullptr, 0);
context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout);
context->OMSetDepthStencilState(psD->dsState, stencilRef);
@ -2281,7 +2400,7 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break;
case QD3D11CommandBuffer::Command::BindComputePipeline:
context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0);
context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0);
break;
case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z);
@ -2388,6 +2507,10 @@ bool QD3D11Buffer::build()
QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer()
{
if (m_type == Dynamic) {
QRHI_RES_RHI(QRhiD3D11);
rhiD->executeBufferHostWrites(this);
}
return { { &buffer }, 1 };
}
@ -3133,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
void QD3D11ShaderResourceBindings::release()
{
sortedBindings.clear();
boundResourceData.clear();
}
bool QD3D11ShaderResourceBindings::build()
@ -3149,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build()
boundResourceData.resize(sortedBindings.count());
QRHI_RES_RHI(QRhiD3D11);
rhiD->updateShaderResourceBindings(this);
for (BoundResourceData &bd : boundResourceData)
memset(&bd, 0, sizeof(BoundResourceData));
generation += 1;
return true;
@ -3191,15 +3315,17 @@ void QD3D11GraphicsPipeline::release()
rastState = nullptr;
}
if (vs) {
vs->Release();
vs = nullptr;
if (vs.shader) {
vs.shader->Release();
vs.shader = nullptr;
}
vs.nativeResourceBindingMap.clear();
if (fs) {
fs->Release();
fs = nullptr;
if (fs.shader) {
fs.shader->Release();
fs.shader = nullptr;
}
fs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
@ -3401,13 +3527,14 @@ static pD3DCompile resolveD3DCompile()
return nullptr;
}
static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error)
static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey)
{
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
return dxbc.shader();
QShaderCode hlslSource = shader.shader({ QShader::HlslShader, 50, shaderVariant });
const QShaderKey key = { QShader::HlslShader, 50, shaderVariant };
QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray();
@ -3459,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray();
}
if (usedShaderKey)
*usedShaderKey = key;
QByteArray result;
result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
@ -3550,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build()
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
vs = static_cast<ID3D11VertexShader *>(cacheIt->s);
vs->AddRef();
vs.shader = static_cast<ID3D11VertexShader *>(cacheIt->s);
vs.shader->AddRef();
vsByteCode = cacheIt->bytecode;
vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
case QRhiShaderStage::Fragment:
fs = static_cast<ID3D11PixelShader *>(cacheIt->s);
fs->AddRef();
fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
fs.shader->AddRef();
fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break;
default:
break;
}
} else {
QString error;
const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error);
QShaderKey shaderKey;
const QByteArray bytecode = compileHlslShaderSource(shaderStage.shader(), shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false;
@ -3576,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build()
switch (shaderStage.type()) {
case QRhiShaderStage::Vertex:
hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs);
hr = rhiD->dev->CreateVertexShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &vs.shader);
if (FAILED(hr)) {
qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
vsByteCode = bytecode;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode));
vs->AddRef();
if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
vs.nativeResourceBindingMap = *map;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
vs.shader->AddRef();
break;
case QRhiShaderStage::Fragment:
hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs);
hr = rhiD->dev->CreatePixelShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &fs.shader);
if (FAILED(hr)) {
qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode));
fs->AddRef();
if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
fs.nativeResourceBindingMap = *map;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
fs.shader->AddRef();
break;
default:
break;
@ -3651,46 +3788,52 @@ void QD3D11ComputePipeline::release()
{
QRHI_RES_RHI(QRhiD3D11);
if (!cs)
if (!cs.shader)
return;
cs->Release();
cs = nullptr;
cs.shader->Release();
cs.shader = nullptr;
cs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this);
}
bool QD3D11ComputePipeline::build()
{
if (cs)
if (cs.shader)
release();
QRHI_RES_RHI(QRhiD3D11);
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) {
cs = static_cast<ID3D11ComputeShader *>(cacheIt->s);
cs.shader = static_cast<ID3D11ComputeShader *>(cacheIt->s);
cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
} else {
QString error;
const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error);
QShaderKey shaderKey;
const QByteArray bytecode = compileHlslShaderSource(m_shaderStage.shader(), m_shaderStage.shaderVariant(), &error, &shaderKey);
if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false;
}
HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs);
HRESULT hr = rhiD->dev->CreateComputeShader(bytecode.constData(), SIZE_T(bytecode.size()), nullptr, &cs.shader);
if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false;
}
if (const QShader::NativeResourceBindingMap *map = m_shaderStage.shader().nativeResourceBindingMap(shaderKey))
cs.nativeResourceBindingMap = *map;
if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache();
rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs, bytecode));
rhiD->m_shaderCache.insert(m_shaderStage, QRhiD3D11::Shader(cs.shader, bytecode, cs.nativeResourceBindingMap));
}
cs->AddRef();
cs.shader->AddRef();
generation += 1;
rhiD->registerResource(this);

View File

@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
ID3D11DepthStencilState *dsState = nullptr;
ID3D11BlendState *blendState = nullptr;
ID3D11VertexShader *vs = nullptr;
ID3D11PixelShader *fs = nullptr;
struct {
ID3D11VertexShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} vs;
struct {
ID3D11PixelShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} fs;
ID3D11InputLayout *inputLayout = nullptr;
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
ID3D11RasterizerState *rastState = nullptr;
@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
void release() override;
bool build() override;
ID3D11ComputeShader *cs = nullptr;
struct {
ID3D11ComputeShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} cs;
uint generation = 0;
friend class QRhiD3D11;
};
@ -642,8 +651,9 @@ public:
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD);
void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD);
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
void executeBufferHostWrites(QD3D11Buffer *bufD);
void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange);
@ -701,9 +711,11 @@ public:
struct Shader {
Shader() = default;
Shader(IUnknown *s, const QByteArray &bytecode) : s(s), bytecode(bytecode) { }
Shader(IUnknown *s, const QByteArray &bytecode, const QShader::NativeResourceBindingMap &rbm)
: s(s), bytecode(bytecode), nativeResourceBindingMap(rbm) { }
IUnknown *s;
QByteArray bytecode;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
};
QHash<QRhiShaderStage, Shader> m_shaderCache;

View File

@ -1827,16 +1827,15 @@ void QRhiMetal::enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdate
}
// this handles all types of buffers, not just Dynamic
void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
void QRhiMetal::executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot)
{
const int idx = bufD->d->slotted ? currentFrameSlot : 0;
if (bufD->d->pendingUpdates[idx].isEmpty())
if (bufD->d->pendingUpdates[slot].isEmpty())
return;
void *p = [bufD->d->buf[idx] contents];
void *p = [bufD->d->buf[slot] contents];
int changeBegin = -1;
int changeEnd = -1;
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[idx])) {
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->d->pendingUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@ -1846,10 +1845,15 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
}
#ifdef Q_OS_MACOS
if (changeBegin >= 0 && bufD->d->managed)
[bufD->d->buf[idx] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
[bufD->d->buf[slot] didModifyRange: NSMakeRange(NSUInteger(changeBegin), NSUInteger(changeEnd - changeBegin))];
#endif
bufD->d->pendingUpdates[idx].clear();
bufD->d->pendingUpdates[slot].clear();
}
void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
{
executeBufferHostWritesForSlot(bufD, bufD->d->slotted ? currentFrameSlot : 0);
}
void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@ -2205,8 +2209,11 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
if (d->slotted) {
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT));
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i)
for (int i = 0; i < QMTL_FRAMES_IN_FLIGHT; ++i) {
QRHI_RES_RHI(QRhiMetal);
rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &d->buf[i];
}
b.slotCount = QMTL_FRAMES_IN_FLIGHT;
return b;
}

View File

@ -437,6 +437,7 @@ public:
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
qsizetype *curOfs);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
static const int SUPPORTED_STAGES = 3;
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD,

View File

@ -149,6 +149,10 @@ QT_BEGIN_NAMESPACE
for other windows as well, as long as they all have their
QWindow::surfaceType() set to QSurface::VulkanSurface.
To request additional extensions to be enabled on the Vulkan device, list them
in deviceExtensions. This can be relevant when integrating with native Vulkan
rendering code.
\section2 Working with existing Vulkan devices
When interoperating with another graphics engine, it may be necessary to
@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
{
inst = params->inst;
maybeWindow = params->window; // may be null
requestedDeviceExtensions = params->deviceExtensions;
importedDevice = importDevice != nullptr;
if (importedDevice) {
@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
devLayers.append("VK_LAYER_LUNARG_standard_validation");
QVulkanInfoVector<QVulkanExtension> devExts;
uint32_t devExtCount = 0;
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
QVector<VkExtensionProperties> devExts(devExtCount);
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data());
if (devExtCount) {
QVector<VkExtensionProperties> extProps(devExtCount);
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, extProps.data());
for (const VkExtensionProperties &p : qAsConst(extProps))
devExts.append({ p.extensionName, p.specVersion });
}
qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count());
QVector<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain");
debugMarkersAvailable = false;
if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
debugMarkersAvailable = true;
}
vertexAttribDivisorAvailable = false;
for (const VkExtensionProperties &ext : devExts) {
if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
debugMarkersAvailable = true;
} else if (!strcmp(ext.extensionName, VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
vertexAttribDivisorAvailable = true;
}
if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
vertexAttribDivisorAvailable = true;
}
}
QByteArrayList envExtList;
if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) {
envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
for (auto ext : requestedDevExts)
envExtList.removeAll(ext);
for (const QByteArray &ext : envExtList) {
if (!ext.isEmpty())
for (const QByteArray &ext : requestedDeviceExtensions) {
if (!ext.isEmpty()) {
if (devExts.contains(ext))
requestedDevExts.append(ext.constData());
else
qWarning("Device extension %s is not supported", ext.constData());
}
}
QByteArrayList envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';');
for (const QByteArray &ext : envExtList) {
if (!ext.isEmpty() && !requestedDevExts.contains(ext)) {
if (devExts.contains(ext))
requestedDevExts.append(ext.constData());
else
qWarning("Device extension %s is not supported", ext.constData());
}
}
if (QRHI_LOG_INFO().isEnabled(QtDebugMsg)) {
qCDebug(QRHI_LOG_INFO, "Enabling device extensions:");
for (const char *ext : requestedDevExts)
qCDebug(QRHI_LOG_INFO, " %s", ext);
}
VkDeviceCreateInfo devInfo;
memset(&devInfo, 0, sizeof(devInfo));
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
@ -2903,7 +2927,7 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
} else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
if (bufD->m_type == QRhiBuffer::Dynamic) {
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWritesForSlot(bufD, currentFrameSlot);
void *p = nullptr;
VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
@ -3300,14 +3324,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
ud->free();
}
void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
void QRhiVulkan::executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot)
{
if (bufD->pendingDynamicUpdates[currentFrameSlot].isEmpty())
if (bufD->pendingDynamicUpdates[slot].isEmpty())
return;
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
void *p = nullptr;
VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
VmaAllocation a = toVmaAllocation(bufD->allocations[slot]);
// The vmaMap/Unmap are basically a no-op when persistently mapped since it
// refcounts; this is great because we don't need to care if the allocation
// was created as persistently mapped or not.
@ -3318,7 +3342,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
}
int changeBegin = -1;
int changeEnd = -1;
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[currentFrameSlot])) {
for (const QRhiResourceUpdateBatchPrivate::BufferOp &u : qAsConst(bufD->pendingDynamicUpdates[slot])) {
Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin)
@ -3330,7 +3354,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
if (changeBegin >= 0)
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin));
bufD->pendingDynamicUpdates[currentFrameSlot].clear();
bufD->pendingDynamicUpdates[slot].clear();
}
static void qrhivk_releaseBuffer(const QRhiVulkan::DeferredReleaseEntry &e, void *allocator)
@ -4166,7 +4190,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0,
@ -4240,7 +4264,7 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot;
QRhiPassResourceTracker::BufferAccess access;
@ -4349,7 +4373,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
bufD->lastActiveFrameSlot = currentFrameSlot;
if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD);
executeBufferHostWritesForSlot(bufD, currentFrameSlot);
const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf
@ -4395,7 +4419,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
ibufD->lastActiveFrameSlot = currentFrameSlot;
if (ibufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(ibufD);
executeBufferHostWritesForSlot(ibufD, currentFrameSlot);
const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
const VkBuffer vkindexbuf = ibufD->buffers[slot];
@ -5188,10 +5212,13 @@ bool QVkBuffer::build()
QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
{
if (m_type == Dynamic) {
QRHI_RES_RHI(QRhiVulkan);
NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT));
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i) {
rhiD->executeBufferHostWritesForSlot(this, i);
b.objects[i] = &buffers[i];
}
b.slotCount = QVK_FRAMES_IN_FLIGHT;
return b;
}
@ -5536,6 +5563,11 @@ QRhiTexture::NativeTexture QVkTexture::nativeTexture()
return {&image, usageState.layout};
}
void QVkTexture::setNativeLayout(int layout)
{
usageState.layout = VkImageLayout(layout);
}
VkImageView QVkTexture::imageViewForLevel(int level)
{
Q_ASSERT(level >= 0 && level < int(mipLevelCount));

View File

@ -57,6 +57,7 @@ struct Q_GUI_EXPORT QRhiVulkanInitParams : public QRhiInitParams
{
QVulkanInstance *inst = nullptr;
QWindow *window = nullptr;
QByteArrayList deviceExtensions;
};
struct Q_GUI_EXPORT QRhiVulkanNativeHandles : public QRhiNativeHandles

View File

@ -123,6 +123,7 @@ struct QVkTexture : public QRhiTexture
bool build() override;
bool buildFrom(NativeTexture src) override;
NativeTexture nativeTexture() override;
void setNativeLayout(int layout) override;
bool prepareBuild(QSize *adjustedSize = nullptr);
bool finishBuild();
@ -778,7 +779,7 @@ public:
size_t *curOfs, void *mp,
BufferImageCopyList *copyInfos);
void enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdateBatch *resourceUpdates);
void executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD);
void executeBufferHostWritesForSlot(QVkBuffer *bufD, int slot);
void enqueueTransitionPassResources(QVkCommandBuffer *cbD);
void recordPrimaryCommandBuffer(QVkCommandBuffer *cbD);
void trackedRegisterBuffer(QRhiPassResourceTracker *passResTracker,
@ -810,6 +811,7 @@ public:
QVulkanInstance *inst = nullptr;
QWindow *maybeWindow = nullptr;
QByteArrayList requestedDeviceExtensions;
bool importedDevice = false;
VkPhysicalDevice physDev = VK_NULL_HANDLE;
VkDevice dev = VK_NULL_HANDLE;

View File

@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->qsbVersion = intVal;
if (d->qsbVersion != QShaderPrivate::QSB_VERSION
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_CBOR
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS)
@ -439,7 +440,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal;
d->stage = Stage(intVal);
if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) {
d->desc = QShaderDescription::deserialize(&ds);
d->desc = QShaderDescription::deserialize(&ds, d->qsbVersion);
} else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
QByteArray descBin;
ds >> descBin;

View File

@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE
struct Q_GUI_EXPORT QShaderPrivate
{
static const int QSB_VERSION = 4;
static const int QSB_VERSION = 5;
static const int QSB_VERSION_WITHOUT_VAR_ARRAYDIMS = 4;
static const int QSB_VERSION_WITH_CBOR = 3;
static const int QSB_VERSION_WITH_BINARY_JSON = 2;
static const int QSB_VERSION_WITHOUT_BINDINGS = 1;

View File

@ -35,6 +35,7 @@
****************************************************************************/
#include "qshaderdescription_p_p.h"
#include "qshader_p_p.h"
#include <QDebug>
#include <QDataStream>
#include <QJsonObject>
@ -402,10 +403,10 @@ QShaderDescription QShaderDescription::fromCbor(const QByteArray &data)
return desc;
}
QShaderDescription QShaderDescription::deserialize(QDataStream *stream)
QShaderDescription QShaderDescription::deserialize(QDataStream *stream, int version)
{
QShaderDescription desc;
QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream);
QShaderDescriptionPrivate::get(&desc)->loadFromStream(stream, version);
return desc;
}
@ -783,6 +784,8 @@ QDebug operator<<(QDebug dbg, const QShaderDescription::InOutVariable &var)
dbg.nospace() << " imageFormat=" << imageFormatStr(var.imageFormat);
if (var.imageFlags)
dbg.nospace() << " imageFlags=" << var.imageFlags;
if (!var.arrayDims.isEmpty())
dbg.nospace() << " array=" << var.arrayDims;
dbg.nospace() << ')';
return dbg;
}
@ -878,6 +881,12 @@ static void addDeco(QJsonObject *obj, const QShaderDescription::InOutVariable &v
(*obj)[imageFormatKey] = imageFormatStr(v.imageFormat);
if (v.imageFlags)
(*obj)[imageFlagsKey] = int(v.imageFlags);
if (!v.arrayDims.isEmpty()) {
QJsonArray dimArr;
for (int dim : v.arrayDims)
dimArr.append(dim);
(*obj)[arrayDimsKey] = dimArr;
}
}
static void serializeDecorations(QDataStream *stream, const QShaderDescription::InOutVariable &v)
@ -887,6 +896,9 @@ static void serializeDecorations(QDataStream *stream, const QShaderDescription::
(*stream) << v.descriptorSet;
(*stream) << int(v.imageFormat);
(*stream) << int(v.imageFlags);
(*stream) << v.arrayDims.count();
for (int dim : v.arrayDims)
(*stream) << dim;
}
static QJsonObject inOutObject(const QShaderDescription::InOutVariable &v)
@ -1124,10 +1136,15 @@ static QShaderDescription::InOutVariable inOutVar(const QJsonObject &obj)
var.imageFormat = mapImageFormat(obj[imageFormatKey].toString());
if (obj.contains(imageFlagsKey))
var.imageFlags = QShaderDescription::ImageFlags(obj[imageFlagsKey].toInt());
if (obj.contains(arrayDimsKey)) {
QJsonArray dimArr = obj[arrayDimsKey].toArray();
for (int i = 0; i < dimArr.count(); ++i)
var.arrayDims.append(dimArr.at(i).toInt());
}
return var;
}
static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOutVariable *v)
static void deserializeDecorations(QDataStream *stream, int version, QShaderDescription::InOutVariable *v)
{
(*stream) >> v->location;
(*stream) >> v->binding;
@ -1137,16 +1154,23 @@ static void deserializeDecorations(QDataStream *stream, QShaderDescription::InOu
v->imageFormat = QShaderDescription::ImageFormat(f);
(*stream) >> f;
v->imageFlags = QShaderDescription::ImageFlags(f);
if (version > QShaderPrivate::QSB_VERSION_WITHOUT_VAR_ARRAYDIMS) {
(*stream) >> f;
v->arrayDims.resize(f);
for (int i = 0; i < f; ++i)
(*stream) >> v->arrayDims[i];
}
}
static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream)
static QShaderDescription::InOutVariable deserializeInOutVar(QDataStream *stream, int version)
{
QShaderDescription::InOutVariable var;
(*stream) >> var.name;
int t;
(*stream) >> t;
var.type = QShaderDescription::VariableType(t);
deserializeDecorations(stream, &var);
deserializeDecorations(stream, version, &var);
return var;
}
@ -1176,7 +1200,7 @@ static QShaderDescription::BlockVariable blockVar(const QJsonObject &obj)
return var;
}
static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream)
static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *stream, int version)
{
QShaderDescription::BlockVariable var;
(*stream) >> var.name;
@ -1196,7 +1220,7 @@ static QShaderDescription::BlockVariable deserializeBlockMemberVar(QDataStream *
(*stream) >> count;
var.structMembers.resize(count);
for (int i = 0; i < count; ++i)
var.structMembers[i] = deserializeBlockMemberVar(stream);
var.structMembers[i] = deserializeBlockMemberVar(stream, version);
return var;
}
@ -1304,7 +1328,7 @@ void QShaderDescriptionPrivate::loadDoc(const QJsonDocument &doc)
}
}
void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream, int version)
{
Q_ASSERT(ref.loadRelaxed() == 1); // must be detached
@ -1312,12 +1336,12 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> count;
inVars.resize(count);
for (int i = 0; i < count; ++i)
inVars[i] = deserializeInOutVar(stream);
inVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
outVars.resize(count);
for (int i = 0; i < count; ++i)
outVars[i] = deserializeInOutVar(stream);
outVars[i] = deserializeInOutVar(stream, version);
(*stream) >> count;
uniformBlocks.resize(count);
@ -1331,7 +1355,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
uniformBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
uniformBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@ -1343,7 +1367,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
pushConstantBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
pushConstantBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@ -1358,7 +1382,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
(*stream) >> memberCount;
storageBlocks[i].members.resize(memberCount);
for (int memberIdx = 0; memberIdx < memberCount; ++memberIdx)
storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream);
storageBlocks[i].members[memberIdx] = deserializeBlockMemberVar(stream, version);
}
(*stream) >> count;
@ -1368,7 +1392,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
combinedImageSamplers[i].type = QShaderDescription::VariableType(t);
deserializeDecorations(stream, &combinedImageSamplers[i]);
deserializeDecorations(stream, version, &combinedImageSamplers[i]);
}
(*stream) >> count;
@ -1378,7 +1402,7 @@ void QShaderDescriptionPrivate::loadFromStream(QDataStream *stream)
int t;
(*stream) >> t;
storageImages[i].type = QShaderDescription::VariableType(t);
deserializeDecorations(stream, &storageImages[i]);
deserializeDecorations(stream, version, &storageImages[i]);
}
for (size_t i = 0; i < 3; ++i)
@ -1420,7 +1444,8 @@ bool operator==(const QShaderDescription::InOutVariable &lhs, const QShaderDescr
&& lhs.binding == rhs.binding
&& lhs.descriptorSet == rhs.descriptorSet
&& lhs.imageFormat == rhs.imageFormat
&& lhs.imageFlags == rhs.imageFlags;
&& lhs.imageFlags == rhs.imageFlags
&& lhs.arrayDims == rhs.arrayDims;
}
/*!

View File

@ -78,7 +78,7 @@ public:
static QShaderDescription fromBinaryJson(const QByteArray &data);
#endif
static QShaderDescription fromCbor(const QByteArray &data);
static QShaderDescription deserialize(QDataStream *stream);
static QShaderDescription deserialize(QDataStream *stream, int version);
enum VariableType {
Unknown = 0,
@ -216,6 +216,7 @@ public:
int descriptorSet = -1;
ImageFormat imageFormat = ImageFormatUnknown;
ImageFlags imageFlags;
QVector<int> arrayDims;
};
struct BlockVariable {

View File

@ -82,7 +82,7 @@ struct Q_GUI_EXPORT QShaderDescriptionPrivate
QJsonDocument makeDoc();
void writeToStream(QDataStream *stream);
void loadDoc(const QJsonDocument &doc);
void loadFromStream(QDataStream *stream);
void loadFromStream(QDataStream *stream, int version);
QAtomicInt ref;
QVector<QShaderDescription::InOutVariable> inVars;

View File

@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top();
blockFormat = list->item(list->count() - 1).blockFormat();
if (list)
blockFormat = list->item(list->count() - 1).blockFormat();
else
qWarning() << "attempted to insert into a list that no longer exists";
}
if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
}
if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat));
} else if (!m_listStack.isEmpty() && m_listItem) {
} else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
m_listStack.top()->add(m_cursor->block());
}
m_needsInsertList = false;

View File

@ -56,6 +56,7 @@
#include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h>
#include <QtCore/qpointer.h>
#include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE
@ -113,7 +114,7 @@ private:
#endif
QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row
QStack<QTextList *> m_listStack;
QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont;
QPalette m_palette;

View File

@ -781,6 +781,8 @@ bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t
system dependent synchronization. For example, on Wayland this will
add send a wl_surface.frame request in order to prevent the driver from
blocking for minimized windows.
\since 5.15
*/
void QVulkanInstance::presentAboutToBeQueued(QWindow *window)
{

View File

@ -1595,19 +1595,6 @@ bool QVulkanWindow::event(QEvent *e)
\sa setQueueCreateInfoModifier()
*/
/*!
Return a previously set queue create info modification function.
\sa setQueueCreateInfoModifier()
\since 5.15
*/
QVulkanWindow::QueueCreateInfoModifier QVulkanWindow::queueCreateInfoModifier() const
{
Q_D(const QVulkanWindow);
return d->queueCreateInfoModifier;
}
/*!
Set a queue create info modification function.

View File

@ -106,7 +106,6 @@ public:
typedef std::function<void(const VkQueueFamilyProperties *,
uint32_t,
QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier;
QueueCreateInfoModifier queueCreateInfoModifier() const;
void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier);
bool isValid() const;

View File

@ -91,7 +91,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
content.
\note Do not delete the object in the slot connected to the
error() or finished() signal. Use deleteLater().
errorOccurred() or finished() signal. Use deleteLater().
\sa QNetworkRequest, QNetworkAccessManager
*/
@ -219,6 +219,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
the server response was detected
\sa error()
\sa errorOccurred()
*/
/*!
@ -362,6 +363,14 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
/*!
\fn void QNetworkReply::error(QNetworkReply::NetworkError code)
\obsolete
Use errorOccurred() instead.
*/
/*!
\fn void QNetworkReply::errorOccurred(QNetworkReply::NetworkError code)
\since 5.15
This signal is emitted when the reply detects an error in
processing. The finished() signal will probably follow, indicating
@ -442,7 +451,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
QNetworkAccessManager functions to do that.
*/
QNetworkReply::QNetworkReply(QObject *parent)
: QIODevice(*new QNetworkReplyPrivate, parent)
: QNetworkReply(*new QNetworkReplyPrivate, parent)
{
}
@ -452,6 +461,8 @@ QNetworkReply::QNetworkReply(QObject *parent)
QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
: QIODevice(dd, parent)
{
// Support the deprecated error() signal:
connect(this, &QNetworkReply::errorOccurred, this, QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error));
}
/*!

View File

@ -156,7 +156,11 @@ public Q_SLOTS:
Q_SIGNALS:
void metaDataChanged();
void finished();
#if QT_DEPRECATED_SINCE(5,15)
QT_DEPRECATED_X("Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead")
void error(QNetworkReply::NetworkError);
#endif
void errorOccurred(QNetworkReply::NetworkError);
#if QT_CONFIG(ssl)
void encrypted();
void sslErrors(const QList<QSslError> &errors);

View File

@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ
const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
"Invalid URI: %1").arg(url.toString());
setError(QNetworkReply::ProtocolFailure, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -2253,7 +2253,7 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
emit q->error(code);
emit q->errorOccurred(code);
}
void QNetworkReplyHttpImplPrivate::_q_metaDataChanged()

View File

@ -855,7 +855,7 @@ void QNetworkReplyImplPrivate::error(QNetworkReplyImpl::NetworkError code, const
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
// maybe we should protect the backend
emit q->error(code);
emit q->errorOccurred(code);
}
void QNetworkReplyImplPrivate::metaDataChanged()
@ -1128,7 +1128,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
"Network access is disabled.");
setError(UnknownNetworkError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -1215,11 +1215,4 @@ int QGifHandler::currentImageNumber() const
return frameNumber;
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QGifHandler::name() const
{
return "gif";
}
#endif
QT_END_NAMESPACE

View File

@ -73,10 +73,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;

View File

@ -809,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image)
return ICOReader::write(device, imgs);
}
#if QT_DEPRECATED_SINCE(5, 13)
/*!
* Return the common identifier of the format.
* For ICO format this will return "ico".
*/
QByteArray QtIcoHandler::name() const
{
return "ico";
}
#endif
/*! \reimp
*/

View File

@ -54,10 +54,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
int imageCount() const override;
bool jumpToImage(int imageNumber) override;
bool jumpToNextImage() override;

View File

@ -1184,11 +1184,4 @@ void QJpegHandler::setOption(ImageOption option, const QVariant &value)
}
}
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QJpegHandler::name() const
{
return "jpeg";
}
#endif
QT_END_NAMESPACE

View File

@ -68,10 +68,6 @@ public:
bool read(QImage *image) override;
bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override;

View File

@ -202,9 +202,7 @@ public:
const QString &path)
: QAbstractFileEngineIterator(filters, nameFilters)
{
m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path), true));
if (m_stack.last()->empty())
m_stack.pop_back();
m_currentIterator = FolderIterator::fromCache(cleanedAssetPath(path), true);
}
QFileInfo currentFileInfo() const override
@ -228,36 +226,23 @@ public:
bool hasNext() const override
{
if (m_stack.empty())
if (!m_currentIterator)
return false;
if (!m_stack.last()->hasNext()) {
m_stack.pop_back();
return hasNext();
}
return true;
return m_currentIterator->hasNext();
}
QString next() override
{
if (m_stack.empty()) {
m_currentIterator.reset();
if (!m_currentIterator)
return {};
}
m_currentIterator = m_stack.last();
auto res = m_currentIterator->next();
if (!res)
return {};
if (res->second.type == AssetItem::Type::Folder) {
m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(currentFilePath()), true));
if (m_stack.last()->empty())
m_stack.pop_back();
}
return res->first;
}
private:
mutable QSharedPointer<FolderIterator> m_currentIterator;
mutable QVector<QSharedPointer<FolderIterator>> m_stack;
QSharedPointer<FolderIterator> m_currentIterator;
};
class AndroidAbstractFileEngine: public QAbstractFileEngine

View File

@ -419,8 +419,7 @@ static QString strippedText(QString s)
[mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) {
const QStringList ext = [self acceptableExtensionsForSave];
[mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)];
[self recomputeAcceptableExtensionsForSave];
} else {
[mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel
}
@ -457,25 +456,49 @@ static QString strippedText(QString s)
}
/*
Returns a list of extensions (e.g. "png", "jpg", "gif")
for the current name filter. If a filter do not conform
to the format *.xyz or * or *.*, an empty list
is returned meaning accept everything.
Computes a list of extensions (e.g. "png", "jpg", "gif")
for the current name filter, and updates the save panel.
If a filter do not conform to the format *.xyz or * or *.*,
all files types are allowed.
Extensions with more than one part (e.g. "tar.gz") are
reduced to their final part, as NSSavePanel does not deal
well with multi-part extensions.
*/
- (QStringList)acceptableExtensionsForSave
- (void)recomputeAcceptableExtensionsForSave
{
QStringList result;
for (int i=0; i<mSelectedNameFilter->count(); ++i) {
const QString &filter = mSelectedNameFilter->at(i);
if (filter.startsWith(QLatin1String("*."))
&& !filter.contains(QLatin1Char('?'))
&& filter.count(QLatin1Char('*')) == 1) {
result += filter.mid(2);
} else {
return QStringList(); // Accept everything
}
QStringList fileTypes;
for (const QString &filter : *mSelectedNameFilter) {
if (!filter.startsWith(QLatin1String("*.")))
continue;
if (filter.contains(QLatin1Char('?')))
continue;
if (filter.count(QLatin1Char('*')) != 1)
continue;
auto extensions = filter.split('.', Qt::SkipEmptyParts);
fileTypes += extensions.last();
// Explicitly show extensions if we detect a filter
// that has a multi-part extension. This prevents
// confusing situations where the user clicks e.g.
// 'foo.tar.gz' and 'foo.tar' is populated in the
// file name box, but when then clicking save macOS
// will warn that the file needs to end in .gz,
// due to thinking the user tried to save the file
// as a 'tar' file instead. Unfortunately this
// property can only be set before the panel is
// shown, so it will not have any effect when
// swithcing filters in an already opened dialog.
if (extensions.size() > 2)
mSavePanel.extensionHidden = NO;
}
return result;
mSavePanel.allowedFileTypes = fileTypes.isEmpty() ? nil
: qt_mac_QStringListToNSMutableArray(fileTypes);
}
- (QString)removeExtensions:(const QString &)filter

View File

@ -107,7 +107,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS
#if QT_CONFIG(vulkan)
} else if (resourceString == "vkSurface") {
if (QVulkanInstance *instance = window->vulkanInstance())
return static_cast<QCocoaVulkanInstance *>(instance->handle())->createSurface(window);
return static_cast<QCocoaVulkanInstance *>(instance->handle())->surface(window);
#endif
}
return nullptr;

View File

@ -61,9 +61,11 @@ public:
void createOrAdoptInstance() override;
VkSurfaceKHR *createSurface(QWindow *window);
VkSurfaceKHR createSurface(NSView *view);
VkSurfaceKHR *surface(QWindow *window);
private:
VkSurfaceKHR createSurface(NSView *view);
QVulkanInstance *m_instance = nullptr;
QLibrary m_lib;
VkSurfaceKHR m_nullSurface = nullptr;

View File

@ -57,12 +57,11 @@ void QCocoaVulkanInstance::createOrAdoptInstance()
initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface"));
}
VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)
VkSurfaceKHR *QCocoaVulkanInstance::surface(QWindow *window)
{
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
if (cocoaWindow->m_vulkanSurface)
destroySurface(cocoaWindow->m_vulkanSurface);
cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
if (!cocoaWindow->m_vulkanSurface)
cocoaWindow->m_vulkanSurface = createSurface(cocoaWindow->m_view);
return &cocoaWindow->m_vulkanSurface;
}
@ -81,7 +80,7 @@ VkSurfaceKHR QCocoaVulkanInstance::createSurface(NSView *view)
surfaceInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
surfaceInfo.pNext = nullptr;
surfaceInfo.flags = 0;
surfaceInfo.pView = view;
surfaceInfo.pView = view.layer;
VkSurfaceKHR surface = nullptr;
VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);

View File

@ -394,16 +394,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev)
d->cosmeticPenSize = 1;
d->current.clipEnabled = false;
d->pixelSize = QPoint(1,1);
QMacCGContext ctx(pdev);
d->hd = CGContextRetain(ctx);
if (d->hd) {
d->saveGraphicsState();
d->orig_xform = CGContextGetCTM(d->hd);
if (d->shading) {
CGShadingRelease(d->shading);
d->shading = nullptr;
if (pdev->devType() != QInternal::Printer) {
QMacCGContext ctx(pdev);
d->hd = CGContextRetain(ctx);
if (d->hd) {
d->saveGraphicsState();
d->orig_xform = CGContextGetCTM(d->hd);
if (d->shading) {
CGShadingRelease(d->shading);
d->shading = nullptr;
}
d->setClip(nullptr); //clear the context's clipping
}
d->setClip(nullptr); //clear the context's clipping
}
setActive(true);

View File

@ -343,7 +343,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested;
requested.flags = window->flags();
requested.geometry = QHighDpi::toNativePixels(window->geometry(), window);
requested.geometry = window->isTopLevel()
? QHighDpi::toNativePixels(window->geometry(), window)
: QHighDpi::toNativeLocalPosition(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid())

View File

@ -424,8 +424,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
if (screen) {
emit contextMenuRequested(globalPos, screen);
emit activated(Context);
if (m_menu)
if (m_menu) {
// Set the foreground window to the controlling window so that clicking outside
// of the menu or window will cause the menu to close
SetForegroundWindow(m_hwnd);
m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
}
}
}
break;

View File

@ -1954,10 +1954,8 @@ void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << (currentScreen ? currentScreen->name() : QString())
<< "\"->\"" << newScreen->name() << '"';
if (mode == FromGeometryChange)
setFlag(SynchronousGeometryChangeEvent);
updateFullFrameMargins();
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()

View File

@ -274,7 +274,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen);
QRect rect = parent()
? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
: QHighDpi::toNativePixels(window()->geometry(), platformScreen);
if (type == Qt::Desktop) {
m_window = platformScreen->root();

View File

@ -131,6 +131,8 @@ void WriteImports::acceptCustomWidget(DomCustomWidget *node)
output << "import " << className << '\n';
} else { // When we do have elementHeader, we know it's a relative import.
QString modulePath = node->elementHeader()->text();
// Replace the '/' by '.'
modulePath.replace(QLatin1Char('/'), QLatin1Char('.'));
// '.h' is added by default on headers for <customwidget>
if (modulePath.endsWith(QLatin1String(".h")))
modulePath.chop(2);

View File

@ -1473,6 +1473,9 @@ void QMenuPrivate::_q_actionTriggered()
}
}
activateCausedStack(list, action, QAction::Trigger, false);
// if a widget action fires, we need to hide the menu explicitly
if (qobject_cast<QWidgetAction*>(action))
hideUpToMenuBar();
}
}
}
@ -1640,10 +1643,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
Widgets can be inserted into menus with the QWidgetAction class.
Instances of this class are used to hold widgets, and are inserted
into menus with the addAction() overload that takes a QAction.
Conversely, actions can be added to widgets with the addAction(),
addActions() and insertAction() functions.
into menus with the addAction() overload that takes a QAction. If the
QWidgetAction fires the triggered() signal, the menu will close.
\warning To make QMenu visible on the screen, exec() or popup() should be
used instead of show().

View File

@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono()
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
/*
Call QTest::qSleep, and return true if the time actually slept is
within \a deviationPercent percent of the requested sleep time.
Otherwise, return false, in which case the test should to abort.
*/
auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool {
auto before = steady_clock::now();
QTest::qSleep(ms);
auto after = steady_clock::now();
auto diff = duration_cast<milliseconds>(after - before).count();
bool inRange = qAbs(diff - ms) < ms * deviationPercent/100.0;
if (!inRange)
qWarning() << "sleeping" << diff << "instead of" << ms << inRange;
return inRange;
};
auto steady_before = steady_clock::now();
auto system_before = system_clock::now();
QTest::qSleep(minResolution);
if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto now = QDeadlineTimer::current(timerType);
QTest::qSleep(minResolution);
auto steady_reference = steady_clock::now();
auto system_reference = system_clock::now();
if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto sampling_start = steady_clock::now();
auto steady_deadline = now.deadline<steady_clock>();
@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono()
}
{
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
auto reference = duration_cast<milliseconds>(steady_after - steady_reference).count();
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_after(steady_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(steady_deadline - steady_before);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
reference = duration_cast<milliseconds>(steady_reference - steady_before).count();
diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_before(steady_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
}
{
auto diff = duration_cast<milliseconds>(system_after - system_deadline);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
QDeadlineTimer dt_after(system_after, timerType);
auto reference = duration_cast<milliseconds>(system_after - system_reference).count();
auto diff = duration_cast<milliseconds>(system_after - system_deadline).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(system_deadline - system_before);
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count())));
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count())));
QDeadlineTimer dt_before(system_before, timerType);
reference = duration_cast<milliseconds>(system_reference - system_before).count();
diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());

View File

@ -48,6 +48,7 @@ private Q_SLOTS:
void validity();
void basics();
void elapsed();
void msecsTo();
};
void tst_QElapsedTimer::statics()
@ -108,30 +109,42 @@ void tst_QElapsedTimer::elapsed()
t1.start();
QTest::qSleep(2*minResolution);
auto nsecs = t1.nsecsElapsed();
auto msecs = t1.elapsed();
QVERIFY(nsecs > 0);
QVERIFY(msecs > 0);
// the number of elapsed nanoseconds and milliseconds should match
QVERIFY(nsecs - msecs * 1000000 < 1000000);
if (msecs > 8 * minResolution)
QSKIP("Sampling timer took too long, aborting test");
QVERIFY(t1.hasExpired(minResolution));
QVERIFY(!t1.hasExpired(8*minResolution));
QVERIFY(!t1.hasExpired(-1));
qint64 elapsed = t1.restart();
QVERIFY(elapsed >= msecs);
QVERIFY(elapsed < msecs + 3*minResolution);
}
void tst_QElapsedTimer::msecsTo()
{
QElapsedTimer t1;
t1.start();
QTest::qSleep(minResolution);
QElapsedTimer t2;
t2.start();
QVERIFY(t1 != t2);
QVERIFY(!(t1 == t2));
QVERIFY(t1 < t2);
QVERIFY(t1.msecsTo(t2) > 0);
QVERIFY(t1.nsecsElapsed() > 0);
QVERIFY(t1.elapsed() > 0);
// the number of elapsed nanoseconds and milliseconds should match
QVERIFY(t1.nsecsElapsed() - t1.elapsed() * 1000000 < 1000000);
QVERIFY(t1.hasExpired(minResolution));
QVERIFY(!t1.hasExpired(8*minResolution));
QVERIFY(!t2.hasExpired(minResolution));
QVERIFY(!t1.hasExpired(-1));
QVERIFY(!t2.hasExpired(-1));
qint64 elapsed = t1.restart();
QVERIFY(elapsed > minResolution);
QVERIFY(elapsed < 3*minResolution);
qint64 diff = t2.msecsTo(t1);
QVERIFY(diff < minResolution);
auto diff = t1.msecsTo(t2);
QVERIFY2(diff > 0, QString("difference t1 and t2 is %1").arg(diff).toLatin1());
diff = t2.msecsTo(t1);
QVERIFY2(diff < 0, QString("difference t2 and t1 is %1").arg(diff).toLatin1());
}
QTEST_MAIN(tst_QElapsedTimer);

View File

@ -5803,6 +5803,8 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r
QVERIFY(list == result);
}
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
list = str.split(sep, QString::KeepEmptyParts);
QVERIFY(list == result);
list = str.split(rx, QString::KeepEmptyParts);
@ -5825,6 +5827,7 @@ void tst_QString::split(const QString &string, const QString &sep, QStringList r
list = str.split(sep.at(0), QString::SkipEmptyParts);
QVERIFY(list == result);
}
QT_WARNING_POP
}
void tst_QString::split()

View File

@ -1115,6 +1115,12 @@ void tst_QHash::keyValueIterator()
entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair);
QCOMPARE(key_value_it->first, pair.first);
QCOMPARE(key_value_it->second, pair.second);
QCOMPARE(&(*key_value_it).first, &it.key());
QCOMPARE(&key_value_it->first, &it.key());
QCOMPARE(&(*key_value_it).second, &it.value());
QCOMPARE(&key_value_it->second, &it.value());
++key_value_it;
++it;
}

View File

@ -881,6 +881,12 @@ void tst_QMap::keyValueIterator()
entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair);
QCOMPARE(key_value_it->first, pair.first);
QCOMPARE(key_value_it->second, pair.second);
QCOMPARE(&(*key_value_it).first, &it.key());
QCOMPARE(&key_value_it->first, &it.key());
QCOMPARE(&(*key_value_it).second, &it.value());
QCOMPARE(&key_value_it->second, &it.value());
++key_value_it;
++it;
}

View File

@ -368,7 +368,7 @@ void tst_QShader::serializeShaderDesc()
QBuffer buf(&data);
QDataStream ds(&buf);
QVERIFY(buf.open(QIODevice::ReadOnly));
QShaderDescription desc2 = QShaderDescription::deserialize(&ds);
QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
QVERIFY(!desc2.isValid());
}
}
@ -400,7 +400,7 @@ void tst_QShader::serializeShaderDesc()
QBuffer buf(&data);
QDataStream ds(&buf);
QVERIFY(buf.open(QIODevice::ReadOnly));
QShaderDescription desc2 = QShaderDescription::deserialize(&ds);
QShaderDescription desc2 = QShaderDescription::deserialize(&ds, QShaderPrivate::QSB_VERSION);
QVERIFY(desc2.isValid());
QCOMPARE(desc, desc2);
}

View File

@ -0,0 +1,5 @@
<t><EFBFBD>
* <20>
<09>
* <20>

View File

@ -0,0 +1 @@
| --:| <?`?><?|`

Some files were not shown because too many files have changed in this diff Show More