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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -131,7 +131,7 @@ void RSSListing::get(const QUrl &url)
currentReply = manager.get(request); currentReply = manager.get(request);
connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead())); connect(currentReply, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(currentReply, SIGNAL(metaDataChanged()), this, SLOT(metaDataChanged())); 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(c++2a): CONFIG += c++2a
qtConfig(c99): CONFIG += c99 qtConfig(c99): CONFIG += c99
qtConfig(c11): CONFIG += c11 qtConfig(c11): CONFIG += c11
qtConfig(separate_debug_info): CONFIG += separate_debug_info
qtConfig(stack-protector-strong): CONFIG += stack_protector_strong qtConfig(stack-protector-strong): CONFIG += stack_protector_strong
contains(TEMPLATE, .*lib) { contains(TEMPLATE, .*lib) {
# module and plugins # module and plugins
unix:qtConfig(reduce_relocations): CONFIG += bsymbolic_functions unix:qtConfig(reduce_relocations): CONFIG += bsymbolic_functions
qtConfig(separate_debug_info): CONFIG += separate_debug_info
!isEmpty(_QMAKE_SUPER_CACHE_): \ !isEmpty(_QMAKE_SUPER_CACHE_): \
rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]* rplbase = $$dirname(_QMAKE_SUPER_CACHE_)/[^/][^/]*

View File

@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
/*! /*!
\since 5.15 \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 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(). from this qfloat16. Serves as qfloat16's equivalent of std::copysign().

View File

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

View File

@ -110,6 +110,7 @@ protected:
QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0); QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0);
virtual void sendPostedEvents(); virtual void sendPostedEvents();
void doUnregisterSocketNotifier(QSocketNotifier *notifier); void doUnregisterSocketNotifier(QSocketNotifier *notifier);
void doUnregisterEventNotifier(QWinEventNotifier *notifier);
private: private:
friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); 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; d->enabled = enable;
QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed();
if (!eventDispatcher) { // perhaps application is shutting down if (!eventDispatcher) // perhaps application is shutting down
if (!enable && d->waitHandle != nullptr)
d->unregisterWaitObject();
return; return;
}
if (Q_UNLIKELY(thread() != QThread::currentThread())) { if (Q_UNLIKELY(thread() != QThread::currentThread())) {
qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread"); qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread");
return; return;

View File

@ -664,7 +664,15 @@ QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, InternalDatabaseEnu
load(data, size); 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) QMimeXMLProvider::QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory)
: QMimeProviderBase(db, directory) : QMimeProviderBase(db, directory)

View File

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

View File

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

View File

@ -1383,6 +1383,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned. 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() \sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/ */
@ -1884,6 +1888,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 3 \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(), \sa toString(), QDateTime::fromString(), QTime::fromString(),
QLocale::toDate() QLocale::toDate()
*/ */
@ -2244,6 +2252,10 @@ QT_WARNING_POP
If the time is invalid, an empty string will be returned. If the time is invalid, an empty string will be returned.
If \a format is empty, the default format "hh:mm:ss" is used. 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() \sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/ */
QString QTime::toString(QStringView format) const QString QTime::toString(QStringView format) const
@ -2641,6 +2653,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 8 \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(), \sa toString(), QDateTime::fromString(), QDate::fromString(),
QLocale::toTime() QLocale::toTime()
*/ */
@ -4541,6 +4557,10 @@ QT_WARNING_POP
If the datetime is invalid, an empty string will be returned. 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() \sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/ */
QString QDateTime::toString(QStringView format) const QString QDateTime::toString(QStringView format) const
@ -5580,6 +5600,10 @@ QT_WARNING_POP
\snippet code/src_corelib_tools_qdatetime.cpp 14 \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(), \sa toString(), QDate::fromString(), QTime::fromString(),
QLocale::toDateTime() 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 /*! \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. 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() \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 \fn template <class Key, class T> int QMultiHash<Key, T>::count(const Key &key, const T &value) const
\since 4.3 \since 4.3

View File

@ -309,10 +309,10 @@ public:
QList<Key> keys(const T &value) const; QList<Key> keys(const T &value) const;
QList<T> values() const; QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15) #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_VERSION_X_5_15("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_VERSION_X_5_15("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;
#endif #endif
int count(const Key &key) const;
class const_iterator; class const_iterator;
@ -512,8 +512,8 @@ public:
iterator insert(const Key &key, const T &value); iterator insert(const Key &key, const T &value);
void insert(const QHash &hash); void insert(const QHash &hash);
#if QT_DEPRECATED_SINCE(5, 15) #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_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_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.") QHash &unite(const QHash &other);
#endif #endif
// STL compatibility // STL compatibility
@ -710,6 +710,19 @@ Q_OUTOFLINE_TEMPLATE QList<T> QHash<Key, T>::values() const
return res; 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> template <class Key, class T>
Q_INLINE_TEMPLATE const T QHash<Key, T>::operator[](const Key &akey) const 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 remove(const Key &key, const T &value);
int count(const Key &key) const;
int count(const Key &key, const T &value) const; int count(const Key &key, const T &value) const;
QList<Key> uniqueKeys() 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); 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> template <class Key, class T>
Q_OUTOFLINE_TEMPLATE QList<Key> QHash<Key, T>::uniqueKeys() const 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; 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) #if !defined(QT_NO_JAVA_STYLE_ITERATORS)
template <class Key, class T> template <class Key, class T>
class QHashIterator class QHashIterator

View File

@ -195,7 +195,6 @@ public:
typedef typename Iterator::iterator_category iterator_category; typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::difference_type difference_type; typedef typename Iterator::difference_type difference_type;
typedef std::pair<Key, T> value_type; typedef std::pair<Key, T> value_type;
typedef const value_type *pointer;
typedef const value_type &reference; typedef const value_type &reference;
QKeyValueIterator() = default; QKeyValueIterator() = default;
@ -206,6 +205,31 @@ public:
return std::pair<Key, T>(i.key(), i.value()); 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; }
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 \internal
*/ */
/*! \typedef QKeyValueIterator::pointer /*! \struct QKeyValueIterator::pointer
\internal \internal
*/ */
@ -75,11 +75,20 @@
Constructs a QKeyValueIterator on top of \a o. 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. 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) /*! \fn template<typename Key, typename T, class Iterator> bool operator==(QKeyValueIterator<Key, T, Iterator> lhs, QKeyValueIterator<Key, T, Iterator> rhs)
\relates QKeyValueIterator \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 /*! \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. 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 /*! \fn template <class Key, class T> int QMap<Key, T>::count() const
@ -2115,11 +2114,6 @@ void QMapDataBase::freeData(QMapDataBase *d)
inserted one. 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 /*! \fn template <class Key, class T> QList<Key> QMultiMap<Key, T>::uniqueKeys() const
\since 4.2 \since 4.2

View File

@ -373,10 +373,10 @@ public:
QList<Key> keys(const T &value) const; QList<Key> keys(const T &value) const;
QList<T> values() const; QList<T> values() const;
#if QT_DEPRECATED_SINCE(5, 15) #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_VERSION_X_5_15("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_VERSION_X_5_15("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;
#endif #endif
int count(const Key &key) const;
inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); } 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); iterator insert(const_iterator pos, const Key &key, const T &value);
void insert(const QMap<Key, T> &map); void insert(const QMap<Key, T> &map);
#if QT_DEPRECATED_SINCE(5, 15) #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_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_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_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_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.") QMap<Key, T> &unite(const QMap<Key, T> &other);
#endif #endif
// STL compatibility // STL compatibility
@ -654,6 +654,23 @@ Q_INLINE_TEMPLATE T &QMap<Key, T>::operator[](const Key &akey)
return n->value; 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> template <class Key, class T>
Q_INLINE_TEMPLATE bool QMap<Key, T>::contains(const Key &akey) const 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 remove(const Key &key, const T &value);
int count(const Key &key) const;
int count(const Key &key, const T &value) const; int count(const Key &key, const T &value) const;
typename QMap<Key, T>::iterator find(const Key &key, const T &value) { 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; 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> template <class Key, class T>
Q_INLINE_TEMPLATE int QMultiMap<Key, T>::count(const Key &key, const T &value) const 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); 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> template<class Key, class T>
typename QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key &key, const T &value) 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); Q_UNUSED(value);
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QBmpHandler::name() const
{
return formatName();
}
#endif
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_BMP #endif // QT_NO_IMAGEFORMAT_BMP

View File

@ -113,9 +113,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

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

View File

@ -69,10 +69,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override; void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const 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(); subType = value.toByteArray().toLower();
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QPpmHandler::name() const
{
return subType.isEmpty() ? QByteArray("ppm") : subType;
}
#endif
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_NO_IMAGEFORMAT_PPM #endif // QT_NO_IMAGEFORMAT_PPM

View File

@ -67,10 +67,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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); static bool canRead(QIODevice *device, QByteArray *subType = nullptr);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

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

View File

@ -66,10 +66,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

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

View File

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

View File

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

View File

@ -298,14 +298,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window) , window(window)
, newGeometry(newGeometry) , newGeometry(newGeometry)
{ {
if (const QPlatformWindow *pw = window->handle()) if (const QPlatformWindow *pw = window->handle()) {
requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window); 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) QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{ {
Q_ASSERT(window); 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()) { if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event // Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect); 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 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 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 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, the type of backing memory used. For buffers backed by host visible memory,
when memory writes become available and visible. Therefore, in general it calling this function guarantees that pending host writes are executed for
is recommended to limit native buffer object access to vertex and index all the returned native buffers.
buffers with types Static or Immutable, because these operate in a
relatively uniform manner with all backends.
\sa QRhi::currentFrameSlot(), QRhi::FramesInFlight \sa QRhi::currentFrameSlot(), QRhi::FramesInFlight
*/ */
@ -2341,6 +2339,31 @@ bool QRhiTexture::buildFrom(QRhiTexture::NativeTexture src)
return false; 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 \class QRhiSampler
\internal \internal

View File

@ -791,6 +791,7 @@ public:
virtual bool build() = 0; virtual bool build() = 0;
virtual NativeTexture nativeTexture(); virtual NativeTexture nativeTexture();
virtual bool buildFrom(NativeTexture src); virtual bool buildFrom(NativeTexture src);
virtual void setNativeLayout(int layout);
protected: protected:
QRhiTexture(QRhiImplementation *rhi, Format format_, const QSize &pixelSize_, 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, void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBindings *srb,
int dynamicOffsetCount, int dynamicOffsetCount,
const QRhiCommandBuffer::DynamicOffset *dynamicOffsets) const QRhiCommandBuffer::DynamicOffset *dynamicOffsets)
@ -608,7 +613,7 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
{ {
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf); QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, b->u.ubuf.buf);
if (bufD->m_type == QRhiBuffer::Dynamic) if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWrites(bufD);
if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) { if (bufD->generation != bd.ubuf.generation || bufD->m_id != bd.ubuf.id) {
srbUpdate = true; srbUpdate = true;
@ -667,8 +672,17 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
} }
} }
if (srbUpdate) if (srbUpdate) {
updateShaderResourceBindings(srbD); 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 srbChanged = gfxPsD ? (cbD->currentGraphicsSrb != srb) : (cbD->currentComputeSrb != srb);
const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation; const bool srbRebuilt = cbD->currentSrbGeneration != srbD->generation;
@ -725,7 +739,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first); QD3D11Buffer *bufD = QRHI_RES(QD3D11Buffer, bindings[i].first);
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic) if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWrites(bufD);
if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer if (cbD->currentVertexBuffers[inputSlot] != bufD->buffer
|| cbD->currentVertexOffsets[inputSlot] != bindings[i].second) || cbD->currentVertexOffsets[inputSlot] != bindings[i].second)
@ -757,7 +771,7 @@ void QRhiD3D11::setVertexInput(QRhiCommandBuffer *cb,
QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf); QD3D11Buffer *ibufD = QRHI_RES(QD3D11Buffer, indexBuf);
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
if (ibufD->m_type == QRhiBuffer::Dynamic) if (ibufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(ibufD); executeBufferHostWrites(ibufD);
const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT const DXGI_FORMAT dxgiFormat = indexFormat == QRhiCommandBuffer::IndexUInt16 ? DXGI_FORMAT_R16_UINT
: DXGI_FORMAT_R32_UINT; : DXGI_FORMAT_R32_UINT;
@ -1774,7 +1788,26 @@ void QRhiD3D11::dispatch(QRhiCommandBuffer *cb, int x, int y, int z)
cbD->commands.append(cmd); 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->vsubufs.clear();
srbD->vsubufoffsets.clear(); srbD->vsubufoffsets.clear();
@ -1799,6 +1832,31 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
srbD->csUAVs.clear(); 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) { for (int i = 0, ie = srbD->sortedBindings.count(); i != ie; ++i) {
const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data(); const QRhiShaderResourceBinding::Data *b = srbD->sortedBindings.at(i).data();
QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]); QD3D11ShaderResourceBindings::BoundResourceData &bd(srbD->boundResourceData[i]);
@ -1818,26 +1876,24 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
// (ByteWidth) is always a multiple of 256. // (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); const uint sizeInConstants = uint(aligned(b->u.ubuf.maybeSize ? b->u.ubuf.maybeSize : bufD->m_size, 256) / 16);
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vsubufs.feed(b->binding, bufD->buffer); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
srbD->vsubufoffsets.feed(b->binding, offsetInConstants); if (nativeBinding.first >= 0)
srbD->vsubufsizes.feed(b->binding, sizeInConstants); res[RBM_VERTEX].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
} }
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fsubufs.feed(b->binding, bufD->buffer); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
srbD->fsubufoffsets.feed(b->binding, offsetInConstants); if (nativeBinding.first >= 0)
srbD->fsubufsizes.feed(b->binding, sizeInConstants); res[RBM_FRAGMENT].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
} }
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
srbD->csubufs.feed(b->binding, bufD->buffer); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
srbD->csubufoffsets.feed(b->binding, offsetInConstants); if (nativeBinding.first >= 0)
srbD->csubufsizes.feed(b->binding, sizeInConstants); res[RBM_COMPUTE].buffers.append({ nativeBinding.first, bufD->buffer, offsetInConstants, sizeInConstants });
} }
} }
break; break;
case QRhiShaderResourceBinding::SampledTexture: 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); QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler); QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texId = texD->m_id; bd.stex.texId = texD->m_id;
@ -1845,16 +1901,25 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.stex.samplerId = samplerD->m_id; bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation; bd.stex.samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
srbD->vssamplers.feed(b->binding, samplerD->samplerState); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
srbD->vsshaderresources.feed(b->binding, texD->srv); 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)) { if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
srbD->fssamplers.feed(b->binding, samplerD->samplerState); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
srbD->fsshaderresources.feed(b->binding, texD->srv); 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)) { if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
srbD->cssamplers.feed(b->binding, samplerD->samplerState); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
srbD->csshaderresources.feed(b->binding, texD->srv); 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; break;
@ -1866,9 +1931,12 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD)
bd.simage.id = texD->m_id; bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation; bd.simage.generation = texD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (uav) if (nativeBinding.first >= 0) {
srbD->csUAVs.feed(b->binding, uav); ID3D11UnorderedAccessView *uav = texD->unorderedAccessViewForLevel(b->u.simage.level);
if (uav)
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
}
} else { } else {
qWarning("Unordered access only supported at compute stage"); 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.id = bufD->m_id;
bd.sbuf.generation = bufD->generation; bd.sbuf.generation = bufD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView(); QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (uav) if (nativeBinding.first >= 0) {
srbD->csUAVs.feed(b->binding, uav); ID3D11UnorderedAccessView *uav = bufD->unorderedAccessView();
if (uav)
res[RBM_COMPUTE].uavs.append({ nativeBinding.first, uav });
}
} else { } else {
qWarning("Unordered access only supported at compute stage"); 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->vsubufs.finish();
srbD->vsubufoffsets.finish(); srbD->vsubufoffsets.finish();
srbD->vsubufsizes.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->fsubufs.finish();
srbD->fsubufoffsets.finish(); srbD->fsubufoffsets.finish();
srbD->fsubufsizes.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->csubufs.finish();
srbD->csubufoffsets.finish(); srbD->csubufoffsets.finish();
srbD->csubufsizes.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->vssamplers.finish();
srbD->vsshaderresources.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->fssamplers.finish();
srbD->fsshaderresources.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->cssamplers.finish();
srbD->csshaderresources.finish(); srbD->csshaderresources.finish();
for (const Stage::Uav &u : qAsConst(res[RBM_COMPUTE].uavs))
srbD->csUAVs.feed(u.ureg, u.uav);
srbD->csUAVs.finish(); srbD->csUAVs.finish();
} }
void QRhiD3D11::executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD) void QRhiD3D11::executeBufferHostWrites(QD3D11Buffer *bufD)
{ {
if (!bufD->hasPendingDynamicUpdates) if (!bufD->hasPendingDynamicUpdates)
return; return;
@ -2205,8 +2324,8 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
case QD3D11CommandBuffer::Command::BindGraphicsPipeline: case QD3D11CommandBuffer::Command::BindGraphicsPipeline:
{ {
QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps; QD3D11GraphicsPipeline *psD = cmd.args.bindGraphicsPipeline.ps;
context->VSSetShader(psD->vs, nullptr, 0); context->VSSetShader(psD->vs.shader, nullptr, 0);
context->PSSetShader(psD->fs, nullptr, 0); context->PSSetShader(psD->fs.shader, nullptr, 0);
context->IASetPrimitiveTopology(psD->d3dTopology); context->IASetPrimitiveTopology(psD->d3dTopology);
context->IASetInputLayout(psD->inputLayout); context->IASetInputLayout(psD->inputLayout);
context->OMSetDepthStencilState(psD->dsState, stencilRef); 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())); annotations->SetMarker(reinterpret_cast<LPCWSTR>(QString::fromLatin1(cmd.args.debugMark.s).utf16()));
break; break;
case QD3D11CommandBuffer::Command::BindComputePipeline: case QD3D11CommandBuffer::Command::BindComputePipeline:
context->CSSetShader(cmd.args.bindComputePipeline.ps->cs, nullptr, 0); context->CSSetShader(cmd.args.bindComputePipeline.ps->cs.shader, nullptr, 0);
break; break;
case QD3D11CommandBuffer::Command::Dispatch: case QD3D11CommandBuffer::Command::Dispatch:
context->Dispatch(cmd.args.dispatch.x, cmd.args.dispatch.y, cmd.args.dispatch.z); 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() QRhiBuffer::NativeBuffer QD3D11Buffer::nativeBuffer()
{ {
if (m_type == Dynamic) {
QRHI_RES_RHI(QRhiD3D11);
rhiD->executeBufferHostWrites(this);
}
return { { &buffer }, 1 }; return { { &buffer }, 1 };
} }
@ -3133,6 +3256,7 @@ QD3D11ShaderResourceBindings::~QD3D11ShaderResourceBindings()
void QD3D11ShaderResourceBindings::release() void QD3D11ShaderResourceBindings::release()
{ {
sortedBindings.clear(); sortedBindings.clear();
boundResourceData.clear();
} }
bool QD3D11ShaderResourceBindings::build() bool QD3D11ShaderResourceBindings::build()
@ -3149,8 +3273,8 @@ bool QD3D11ShaderResourceBindings::build()
boundResourceData.resize(sortedBindings.count()); boundResourceData.resize(sortedBindings.count());
QRHI_RES_RHI(QRhiD3D11); for (BoundResourceData &bd : boundResourceData)
rhiD->updateShaderResourceBindings(this); memset(&bd, 0, sizeof(BoundResourceData));
generation += 1; generation += 1;
return true; return true;
@ -3191,15 +3315,17 @@ void QD3D11GraphicsPipeline::release()
rastState = nullptr; rastState = nullptr;
} }
if (vs) { if (vs.shader) {
vs->Release(); vs.shader->Release();
vs = nullptr; vs.shader = nullptr;
} }
vs.nativeResourceBindingMap.clear();
if (fs) { if (fs.shader) {
fs->Release(); fs.shader->Release();
fs = nullptr; fs.shader = nullptr;
} }
fs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this); rhiD->unregisterResource(this);
} }
@ -3401,13 +3527,14 @@ static pD3DCompile resolveD3DCompile()
return nullptr; 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 }); QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty()) if (!dxbc.shader().isEmpty())
return dxbc.shader(); 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()) { if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader; qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;
return QByteArray(); return QByteArray();
@ -3459,6 +3586,9 @@ static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Varian
return QByteArray(); return QByteArray();
} }
if (usedShaderKey)
*usedShaderKey = key;
QByteArray result; QByteArray result;
result.resize(int(bytecode->GetBufferSize())); result.resize(int(bytecode->GetBufferSize()));
memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size())); memcpy(result.data(), bytecode->GetBufferPointer(), size_t(result.size()));
@ -3550,20 +3680,23 @@ bool QD3D11GraphicsPipeline::build()
if (cacheIt != rhiD->m_shaderCache.constEnd()) { if (cacheIt != rhiD->m_shaderCache.constEnd()) {
switch (shaderStage.type()) { switch (shaderStage.type()) {
case QRhiShaderStage::Vertex: case QRhiShaderStage::Vertex:
vs = static_cast<ID3D11VertexShader *>(cacheIt->s); vs.shader = static_cast<ID3D11VertexShader *>(cacheIt->s);
vs->AddRef(); vs.shader->AddRef();
vsByteCode = cacheIt->bytecode; vsByteCode = cacheIt->bytecode;
vs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break; break;
case QRhiShaderStage::Fragment: case QRhiShaderStage::Fragment:
fs = static_cast<ID3D11PixelShader *>(cacheIt->s); fs.shader = static_cast<ID3D11PixelShader *>(cacheIt->s);
fs->AddRef(); fs.shader->AddRef();
fs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
break; break;
default: default:
break; break;
} }
} else { } else {
QString error; 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()) { if (bytecode.isEmpty()) {
qWarning("HLSL shader compilation failed: %s", qPrintable(error)); qWarning("HLSL shader compilation failed: %s", qPrintable(error));
return false; return false;
@ -3576,23 +3709,27 @@ bool QD3D11GraphicsPipeline::build()
switch (shaderStage.type()) { switch (shaderStage.type()) {
case QRhiShaderStage::Vertex: 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)) { if (FAILED(hr)) {
qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to create vertex shader: %s", qPrintable(comErrorMessage(hr)));
return false; return false;
} }
vsByteCode = bytecode; vsByteCode = bytecode;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs, bytecode)); if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
vs->AddRef(); vs.nativeResourceBindingMap = *map;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(vs.shader, bytecode, vs.nativeResourceBindingMap));
vs.shader->AddRef();
break; break;
case QRhiShaderStage::Fragment: 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)) { if (FAILED(hr)) {
qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to create pixel shader: %s", qPrintable(comErrorMessage(hr)));
return false; return false;
} }
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs, bytecode)); if (const QShader::NativeResourceBindingMap *map = shaderStage.shader().nativeResourceBindingMap(shaderKey))
fs->AddRef(); fs.nativeResourceBindingMap = *map;
rhiD->m_shaderCache.insert(shaderStage, QRhiD3D11::Shader(fs.shader, bytecode, fs.nativeResourceBindingMap));
fs.shader->AddRef();
break; break;
default: default:
break; break;
@ -3651,46 +3788,52 @@ void QD3D11ComputePipeline::release()
{ {
QRHI_RES_RHI(QRhiD3D11); QRHI_RES_RHI(QRhiD3D11);
if (!cs) if (!cs.shader)
return; return;
cs->Release(); cs.shader->Release();
cs = nullptr; cs.shader = nullptr;
cs.nativeResourceBindingMap.clear();
rhiD->unregisterResource(this); rhiD->unregisterResource(this);
} }
bool QD3D11ComputePipeline::build() bool QD3D11ComputePipeline::build()
{ {
if (cs) if (cs.shader)
release(); release();
QRHI_RES_RHI(QRhiD3D11); QRHI_RES_RHI(QRhiD3D11);
auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage); auto cacheIt = rhiD->m_shaderCache.constFind(m_shaderStage);
if (cacheIt != rhiD->m_shaderCache.constEnd()) { if (cacheIt != rhiD->m_shaderCache.constEnd()) {
cs = static_cast<ID3D11ComputeShader *>(cacheIt->s); cs.shader = static_cast<ID3D11ComputeShader *>(cacheIt->s);
cs.nativeResourceBindingMap = cacheIt->nativeResourceBindingMap;
} else { } else {
QString error; 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()) { if (bytecode.isEmpty()) {
qWarning("HLSL compute shader compilation failed: %s", qPrintable(error)); qWarning("HLSL compute shader compilation failed: %s", qPrintable(error));
return false; 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)) { if (FAILED(hr)) {
qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr))); qWarning("Failed to create compute shader: %s", qPrintable(comErrorMessage(hr)));
return false; 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) if (rhiD->m_shaderCache.count() >= QRhiD3D11::MAX_SHADER_CACHE_ENTRIES)
rhiD->clearShaderCache(); 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; generation += 1;
rhiD->registerResource(this); rhiD->registerResource(this);

View File

@ -270,8 +270,14 @@ struct QD3D11GraphicsPipeline : public QRhiGraphicsPipeline
ID3D11DepthStencilState *dsState = nullptr; ID3D11DepthStencilState *dsState = nullptr;
ID3D11BlendState *blendState = nullptr; ID3D11BlendState *blendState = nullptr;
ID3D11VertexShader *vs = nullptr; struct {
ID3D11PixelShader *fs = nullptr; ID3D11VertexShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} vs;
struct {
ID3D11PixelShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} fs;
ID3D11InputLayout *inputLayout = nullptr; ID3D11InputLayout *inputLayout = nullptr;
D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; D3D11_PRIMITIVE_TOPOLOGY d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
ID3D11RasterizerState *rastState = nullptr; ID3D11RasterizerState *rastState = nullptr;
@ -286,7 +292,10 @@ struct QD3D11ComputePipeline : public QRhiComputePipeline
void release() override; void release() override;
bool build() override; bool build() override;
ID3D11ComputeShader *cs = nullptr; struct {
ID3D11ComputeShader *shader = nullptr;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
} cs;
uint generation = 0; uint generation = 0;
friend class QRhiD3D11; friend class QRhiD3D11;
}; };
@ -642,8 +651,9 @@ public:
void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD, void enqueueSubresUpload(QD3D11Texture *texD, QD3D11CommandBuffer *cbD,
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc); int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD); void updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
void executeBufferHostWritesForCurrentFrame(QD3D11Buffer *bufD); const QShader::NativeResourceBindingMap *nativeResourceBindingMaps[]);
void executeBufferHostWrites(QD3D11Buffer *bufD);
void bindShaderResources(QD3D11ShaderResourceBindings *srbD, void bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount, const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange); bool offsetOnlyChange);
@ -701,9 +711,11 @@ public:
struct Shader { struct Shader {
Shader() = default; 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; IUnknown *s;
QByteArray bytecode; QByteArray bytecode;
QShader::NativeResourceBindingMap nativeResourceBindingMap;
}; };
QHash<QRhiShaderStage, Shader> m_shaderCache; 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 // 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[slot].isEmpty())
if (bufD->d->pendingUpdates[idx].isEmpty())
return; return;
void *p = [bufD->d->buf[idx] contents]; void *p = [bufD->d->buf[slot] contents];
int changeBegin = -1; int changeBegin = -1;
int changeEnd = -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)); Q_ASSERT(bufD == QRHI_RES(QMetalBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size())); memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin) if (changeBegin == -1 || u.offset < changeBegin)
@ -1846,10 +1845,15 @@ void QRhiMetal::executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD)
} }
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
if (changeBegin >= 0 && bufD->d->managed) 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 #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) void QRhiMetal::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
@ -2205,8 +2209,11 @@ QRhiBuffer::NativeBuffer QMetalBuffer::nativeBuffer()
if (d->slotted) { if (d->slotted) {
NativeBuffer b; NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QMTL_FRAMES_IN_FLIGHT)); 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.objects[i] = &d->buf[i];
}
b.slotCount = QMTL_FRAMES_IN_FLIGHT; b.slotCount = QMTL_FRAMES_IN_FLIGHT;
return b; return b;
} }

View File

@ -437,6 +437,7 @@ public:
int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc, int layer, int level, const QRhiTextureSubresourceUploadDescription &subresDesc,
qsizetype *curOfs); qsizetype *curOfs);
void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates); void enqueueResourceUpdates(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates);
void executeBufferHostWritesForSlot(QMetalBuffer *bufD, int slot);
void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD); void executeBufferHostWritesForCurrentFrame(QMetalBuffer *bufD);
static const int SUPPORTED_STAGES = 3; static const int SUPPORTED_STAGES = 3;
void enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD, 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 for other windows as well, as long as they all have their
QWindow::surfaceType() set to QSurface::VulkanSurface. 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 \section2 Working with existing Vulkan devices
When interoperating with another graphics engine, it may be necessary to When interoperating with another graphics engine, it may be necessary to
@ -299,6 +303,7 @@ QRhiVulkan::QRhiVulkan(QRhiVulkanInitParams *params, QRhiVulkanNativeHandles *im
{ {
inst = params->inst; inst = params->inst;
maybeWindow = params->window; // may be null maybeWindow = params->window; // may be null
requestedDeviceExtensions = params->deviceExtensions;
importedDevice = importDevice != nullptr; importedDevice = importDevice != nullptr;
if (importedDevice) { if (importedDevice) {
@ -463,40 +468,59 @@ bool QRhiVulkan::create(QRhi::Flags flags)
if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation")) if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
devLayers.append("VK_LAYER_LUNARG_standard_validation"); devLayers.append("VK_LAYER_LUNARG_standard_validation");
QVulkanInfoVector<QVulkanExtension> devExts;
uint32_t devExtCount = 0; uint32_t devExtCount = 0;
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr); f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, nullptr);
QVector<VkExtensionProperties> devExts(devExtCount); if (devExtCount) {
f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &devExtCount, devExts.data()); 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()); qCDebug(QRHI_LOG_INFO, "%d device extensions available", devExts.count());
QVector<const char *> requestedDevExts; QVector<const char *> requestedDevExts;
requestedDevExts.append("VK_KHR_swapchain"); requestedDevExts.append("VK_KHR_swapchain");
debugMarkersAvailable = false; debugMarkersAvailable = false;
if (devExts.contains(VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) {
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
debugMarkersAvailable = true;
}
vertexAttribDivisorAvailable = false; vertexAttribDivisorAvailable = false;
for (const VkExtensionProperties &ext : devExts) { if (devExts.contains(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME)) {
if (!strcmp(ext.extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME)) { if (inst->extensions().contains(QByteArrayLiteral("VK_KHR_get_physical_device_properties2"))) {
requestedDevExts.append(VK_EXT_DEBUG_MARKER_EXTENSION_NAME); requestedDevExts.append(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
debugMarkersAvailable = true; vertexAttribDivisorAvailable = 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;
}
} }
} }
QByteArrayList envExtList; for (const QByteArray &ext : requestedDeviceExtensions) {
if (qEnvironmentVariableIsSet("QT_VULKAN_DEVICE_EXTENSIONS")) { if (!ext.isEmpty()) {
envExtList = qgetenv("QT_VULKAN_DEVICE_EXTENSIONS").split(';'); if (devExts.contains(ext))
for (auto ext : requestedDevExts)
envExtList.removeAll(ext);
for (const QByteArray &ext : envExtList) {
if (!ext.isEmpty())
requestedDevExts.append(ext.constData()); 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; VkDeviceCreateInfo devInfo;
memset(&devInfo, 0, sizeof(devInfo)); memset(&devInfo, 0, sizeof(devInfo));
devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 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) { } else if (u.type == QRhiResourceUpdateBatchPrivate::BufferOp::Read) {
QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf); QVkBuffer *bufD = QRHI_RES(QVkBuffer, u.buf);
if (bufD->m_type == QRhiBuffer::Dynamic) { if (bufD->m_type == QRhiBuffer::Dynamic) {
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWritesForSlot(bufD, currentFrameSlot);
void *p = nullptr; void *p = nullptr;
VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]); VmaAllocation a = toVmaAllocation(bufD->allocations[currentFrameSlot]);
VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p); VkResult err = vmaMapMemory(toVmaAllocator(allocator), a, &p);
@ -3300,14 +3324,14 @@ void QRhiVulkan::enqueueResourceUpdates(QVkCommandBuffer *cbD, QRhiResourceUpdat
ud->free(); 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; return;
Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic); Q_ASSERT(bufD->m_type == QRhiBuffer::Dynamic);
void *p = nullptr; 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 // 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 // refcounts; this is great because we don't need to care if the allocation
// was created as persistently mapped or not. // was created as persistently mapped or not.
@ -3318,7 +3342,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
} }
int changeBegin = -1; int changeBegin = -1;
int changeEnd = -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)); Q_ASSERT(bufD == QRHI_RES(QVkBuffer, u.buf));
memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size())); memcpy(static_cast<char *>(p) + u.offset, u.data.constData(), size_t(u.data.size()));
if (changeBegin == -1 || u.offset < changeBegin) if (changeBegin == -1 || u.offset < changeBegin)
@ -3330,7 +3354,7 @@ void QRhiVulkan::executeBufferHostWritesForCurrentFrame(QVkBuffer *bufD)
if (changeBegin >= 0) if (changeBegin >= 0)
vmaFlushAllocation(toVmaAllocator(allocator), a, VkDeviceSize(changeBegin), VkDeviceSize(changeEnd - changeBegin)); 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) 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)); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::UniformBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic) if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot; bufD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterBuffer(&passResTracker, bufD, bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0, 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)); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::StorageBuffer));
if (bufD->m_type == QRhiBuffer::Dynamic) if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWritesForSlot(bufD, currentFrameSlot);
bufD->lastActiveFrameSlot = currentFrameSlot; bufD->lastActiveFrameSlot = currentFrameSlot;
QRhiPassResourceTracker::BufferAccess access; QRhiPassResourceTracker::BufferAccess access;
@ -4349,7 +4373,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer)); Q_ASSERT(bufD->m_usage.testFlag(QRhiBuffer::VertexBuffer));
bufD->lastActiveFrameSlot = currentFrameSlot; bufD->lastActiveFrameSlot = currentFrameSlot;
if (bufD->m_type == QRhiBuffer::Dynamic) if (bufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(bufD); executeBufferHostWritesForSlot(bufD, currentFrameSlot);
const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0]; const VkBuffer vkvertexbuf = bufD->buffers[bufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0];
if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf if (cbD->currentVertexBuffers[inputSlot] != vkvertexbuf
@ -4395,7 +4419,7 @@ void QRhiVulkan::setVertexInput(QRhiCommandBuffer *cb,
Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer)); Q_ASSERT(ibufD->m_usage.testFlag(QRhiBuffer::IndexBuffer));
ibufD->lastActiveFrameSlot = currentFrameSlot; ibufD->lastActiveFrameSlot = currentFrameSlot;
if (ibufD->m_type == QRhiBuffer::Dynamic) if (ibufD->m_type == QRhiBuffer::Dynamic)
executeBufferHostWritesForCurrentFrame(ibufD); executeBufferHostWritesForSlot(ibufD, currentFrameSlot);
const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0; const int slot = ibufD->m_type == QRhiBuffer::Dynamic ? currentFrameSlot : 0;
const VkBuffer vkindexbuf = ibufD->buffers[slot]; const VkBuffer vkindexbuf = ibufD->buffers[slot];
@ -5188,10 +5212,13 @@ bool QVkBuffer::build()
QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer() QRhiBuffer::NativeBuffer QVkBuffer::nativeBuffer()
{ {
if (m_type == Dynamic) { if (m_type == Dynamic) {
QRHI_RES_RHI(QRhiVulkan);
NativeBuffer b; NativeBuffer b;
Q_ASSERT(sizeof(b.objects) / sizeof(b.objects[0]) >= size_t(QVK_FRAMES_IN_FLIGHT)); 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.objects[i] = &buffers[i];
}
b.slotCount = QVK_FRAMES_IN_FLIGHT; b.slotCount = QVK_FRAMES_IN_FLIGHT;
return b; return b;
} }
@ -5536,6 +5563,11 @@ QRhiTexture::NativeTexture QVkTexture::nativeTexture()
return {&image, usageState.layout}; return {&image, usageState.layout};
} }
void QVkTexture::setNativeLayout(int layout)
{
usageState.layout = VkImageLayout(layout);
}
VkImageView QVkTexture::imageViewForLevel(int level) VkImageView QVkTexture::imageViewForLevel(int level)
{ {
Q_ASSERT(level >= 0 && level < int(mipLevelCount)); Q_ASSERT(level >= 0 && level < int(mipLevelCount));

View File

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

View File

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

View File

@ -428,6 +428,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal; ds >> intVal;
d->qsbVersion = intVal; d->qsbVersion = intVal;
if (d->qsbVersion != QShaderPrivate::QSB_VERSION 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_CBOR
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON
&& d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS) && d->qsbVersion != QShaderPrivate::QSB_VERSION_WITHOUT_BINDINGS)
@ -439,7 +440,7 @@ QShader QShader::fromSerialized(const QByteArray &data)
ds >> intVal; ds >> intVal;
d->stage = Stage(intVal); d->stage = Stage(intVal);
if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_CBOR) { 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) { } else if (d->qsbVersion > QShaderPrivate::QSB_VERSION_WITH_BINARY_JSON) {
QByteArray descBin; QByteArray descBin;
ds >> descBin; ds >> descBin;

View File

@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE
struct Q_GUI_EXPORT QShaderPrivate 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_CBOR = 3;
static const int QSB_VERSION_WITH_BINARY_JSON = 2; static const int QSB_VERSION_WITH_BINARY_JSON = 2;
static const int QSB_VERSION_WITHOUT_BINDINGS = 1; static const int QSB_VERSION_WITHOUT_BINDINGS = 1;

View File

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

View File

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

View File

@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat; QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) { if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top(); 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) { if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth); blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
} }
if (m_needsInsertList) { if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat)); 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_listStack.top()->add(m_cursor->block());
} }
m_needsInsertList = false; m_needsInsertList = false;

View File

@ -56,6 +56,7 @@
#include <QtGui/qpalette.h> #include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h> #include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h> #include <QtGui/qtextlist.h>
#include <QtCore/qpointer.h>
#include <QtCore/qstack.h> #include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -113,7 +114,7 @@ private:
#endif #endif
QString m_blockCodeLanguage; QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row QVector<int> m_nonEmptyTableCells; // in the current row
QStack<QTextList *> m_listStack; QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack; QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont; QFont m_monoFont;
QPalette m_palette; 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 system dependent synchronization. For example, on Wayland this will
add send a wl_surface.frame request in order to prevent the driver from add send a wl_surface.frame request in order to prevent the driver from
blocking for minimized windows. blocking for minimized windows.
\since 5.15
*/ */
void QVulkanInstance::presentAboutToBeQueued(QWindow *window) void QVulkanInstance::presentAboutToBeQueued(QWindow *window)
{ {

View File

@ -1595,19 +1595,6 @@ bool QVulkanWindow::event(QEvent *e)
\sa setQueueCreateInfoModifier() \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. Set a queue create info modification function.

View File

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

View File

@ -91,7 +91,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
content. content.
\note Do not delete the object in the slot connected to the \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 \sa QNetworkRequest, QNetworkAccessManager
*/ */
@ -219,6 +219,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
the server response was detected the server response was detected
\sa error() \sa error()
\sa errorOccurred()
*/ */
/*! /*!
@ -362,6 +363,14 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
/*! /*!
\fn void QNetworkReply::error(QNetworkReply::NetworkError code) \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 This signal is emitted when the reply detects an error in
processing. The finished() signal will probably follow, indicating processing. The finished() signal will probably follow, indicating
@ -442,7 +451,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
QNetworkAccessManager functions to do that. QNetworkAccessManager functions to do that.
*/ */
QNetworkReply::QNetworkReply(QObject *parent) 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) QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
: QIODevice(dd, 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: Q_SIGNALS:
void metaDataChanged(); void metaDataChanged();
void finished(); void finished();
#if QT_DEPRECATED_SINCE(5,15)
QT_DEPRECATED_X("Use QNetworkReply::errorOccurred(QNetworkReply::NetworkError) instead")
void error(QNetworkReply::NetworkError); void error(QNetworkReply::NetworkError);
#endif
void errorOccurred(QNetworkReply::NetworkError);
#if QT_CONFIG(ssl) #if QT_CONFIG(ssl)
void encrypted(); void encrypted();
void sslErrors(const QList<QSslError> &errors); void sslErrors(const QList<QSslError> &errors);

View File

@ -88,7 +88,7 @@ QNetworkReplyDataImpl::QNetworkReplyDataImpl(QObject *parent, const QNetworkRequ
const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend", const QString msg = QCoreApplication::translate("QNetworkAccessDataBackend",
"Invalid URI: %1").arg(url.toString()); "Invalid URI: %1").arg(url.toString());
setError(QNetworkReply::ProtocolFailure, msg); setError(QNetworkReply::ProtocolFailure, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure)); Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolFailure));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); 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 // note: might not be a good idea, since users could decide to delete us
// which would delete the backend too... // which would delete the backend too...
// maybe we should protect the backend // maybe we should protect the backend
emit q->error(code); emit q->errorOccurred(code);
} }
void QNetworkReplyHttpImplPrivate::_q_metaDataChanged() 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 // note: might not be a good idea, since users could decide to delete us
// which would delete the backend too... // which would delete the backend too...
// maybe we should protect the backend // maybe we should protect the backend
emit q->error(code); emit q->errorOccurred(code);
} }
void QNetworkReplyImplPrivate::metaDataChanged() void QNetworkReplyImplPrivate::metaDataChanged()
@ -1128,7 +1128,7 @@ QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
"Network access is disabled."); "Network access is disabled.");
setError(UnknownNetworkError, msg); setError(UnknownNetworkError, msg);
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection,
Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError)); Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
} }

View File

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

View File

@ -73,10 +73,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

@ -809,17 +809,6 @@ bool QtIcoHandler::write(const QImage &image)
return ICOReader::write(device, imgs); 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 /*! \reimp
*/ */

View File

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

View File

@ -68,10 +68,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const 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); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

@ -202,9 +202,7 @@ public:
const QString &path) const QString &path)
: QAbstractFileEngineIterator(filters, nameFilters) : QAbstractFileEngineIterator(filters, nameFilters)
{ {
m_stack.push_back(FolderIterator::fromCache(cleanedAssetPath(path), true)); m_currentIterator = FolderIterator::fromCache(cleanedAssetPath(path), true);
if (m_stack.last()->empty())
m_stack.pop_back();
} }
QFileInfo currentFileInfo() const override QFileInfo currentFileInfo() const override
@ -228,36 +226,23 @@ public:
bool hasNext() const override bool hasNext() const override
{ {
if (m_stack.empty()) if (!m_currentIterator)
return false; return false;
if (!m_stack.last()->hasNext()) { return m_currentIterator->hasNext();
m_stack.pop_back();
return hasNext();
}
return true;
} }
QString next() override QString next() override
{ {
if (m_stack.empty()) { if (!m_currentIterator)
m_currentIterator.reset();
return {}; return {};
}
m_currentIterator = m_stack.last();
auto res = m_currentIterator->next(); auto res = m_currentIterator->next();
if (!res) if (!res)
return {}; 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; return res->first;
} }
private: private:
mutable QSharedPointer<FolderIterator> m_currentIterator; QSharedPointer<FolderIterator> m_currentIterator;
mutable QVector<QSharedPointer<FolderIterator>> m_stack;
}; };
class AndroidAbstractFileEngine: public QAbstractFileEngine 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? [mPopUpButton setHidden:chooseDirsOnly]; // TODO hide the whole sunken pane instead?
if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) { if (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) {
const QStringList ext = [self acceptableExtensionsForSave]; [self recomputeAcceptableExtensionsForSave];
[mSavePanel setAllowedFileTypes:ext.isEmpty() ? nil : qt_mac_QStringListToNSMutableArray(ext)];
} else { } else {
[mOpenPanel setAllowedFileTypes:nil]; // delegate panel:shouldEnableURL: does the file filtering for NSOpenPanel [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") Computes a list of extensions (e.g. "png", "jpg", "gif")
for the current name filter. If a filter do not conform for the current name filter, and updates the save panel.
to the format *.xyz or * or *.*, an empty list
is returned meaning accept everything. 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; QStringList fileTypes;
for (int i=0; i<mSelectedNameFilter->count(); ++i) { for (const QString &filter : *mSelectedNameFilter) {
const QString &filter = mSelectedNameFilter->at(i); if (!filter.startsWith(QLatin1String("*.")))
if (filter.startsWith(QLatin1String("*.")) continue;
&& !filter.contains(QLatin1Char('?'))
&& filter.count(QLatin1Char('*')) == 1) { if (filter.contains(QLatin1Char('?')))
result += filter.mid(2); continue;
} else {
return QStringList(); // Accept everything 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 - (QString)removeExtensions:(const QString &)filter

View File

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

View File

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

View File

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

View File

@ -394,16 +394,19 @@ QCoreGraphicsPaintEngine::begin(QPaintDevice *pdev)
d->cosmeticPenSize = 1; d->cosmeticPenSize = 1;
d->current.clipEnabled = false; d->current.clipEnabled = false;
d->pixelSize = QPoint(1,1); d->pixelSize = QPoint(1,1);
QMacCGContext ctx(pdev);
d->hd = CGContextRetain(ctx); if (pdev->devType() != QInternal::Printer) {
if (d->hd) { QMacCGContext ctx(pdev);
d->saveGraphicsState(); d->hd = CGContextRetain(ctx);
d->orig_xform = CGContextGetCTM(d->hd); if (d->hd) {
if (d->shading) { d->saveGraphicsState();
CGShadingRelease(d->shading); d->orig_xform = CGContextGetCTM(d->hd);
d->shading = nullptr; 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); setActive(true);

View File

@ -343,7 +343,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested; QWindowsWindowData requested;
requested.flags = window->flags(); 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())). // Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins"); const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid()) if (customMarginsV.isValid())

View File

@ -424,8 +424,12 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
if (screen) { if (screen) {
emit contextMenuRequested(globalPos, screen); emit contextMenuRequested(globalPos, screen);
emit activated(Context); 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()); m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
}
} }
} }
break; break;

View File

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

View File

@ -274,7 +274,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen(); 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) { if (type == Qt::Desktop) {
m_window = platformScreen->root(); m_window = platformScreen->root();

View File

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

View File

@ -1473,6 +1473,9 @@ void QMenuPrivate::_q_actionTriggered()
} }
} }
activateCausedStack(list, action, QAction::Trigger, false); 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. Widgets can be inserted into menus with the QWidgetAction class.
Instances of this class are used to hold widgets, and are inserted Instances of this class are used to hold widgets, and are inserted
into menus with the addAction() overload that takes a QAction. into menus with the addAction() overload that takes a QAction. If the
QWidgetAction fires the triggered() signal, the menu will close.
Conversely, actions can be added to widgets with the addAction(),
addActions() and insertAction() functions.
\warning To make QMenu visible on the screen, exec() or popup() should be \warning To make QMenu visible on the screen, exec() or popup() should be
used instead of show(). used instead of show().

View File

@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono()
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero()); 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 steady_before = steady_clock::now();
auto system_before = system_clock::now(); auto system_before = system_clock::now();
QTest::qSleep(minResolution); if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto now = QDeadlineTimer::current(timerType); 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 sampling_start = steady_clock::now();
auto steady_deadline = now.deadline<steady_clock>(); auto steady_deadline = now.deadline<steady_clock>();
@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono()
} }
{ {
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline); auto reference = duration_cast<milliseconds>(steady_after - steady_reference).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); auto diff = duration_cast<milliseconds>(steady_after - steady_deadline).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_after(steady_after, timerType); QDeadlineTimer dt_after(steady_after, timerType);
QVERIFY2(now < dt_after, QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(steady_deadline - steady_before); reference = duration_cast<milliseconds>(steady_reference - steady_before).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_before(steady_before, timerType); QDeadlineTimer dt_before(steady_before, timerType);
QVERIFY2(now > dt_before, QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
} }
{ {
auto diff = duration_cast<milliseconds>(system_after - system_deadline); auto reference = duration_cast<milliseconds>(system_after - system_reference).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); auto diff = duration_cast<milliseconds>(system_after - system_deadline).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
QDeadlineTimer dt_after(system_after, timerType);
QVERIFY2(now < dt_after, QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(system_deadline - system_before); reference = duration_cast<milliseconds>(system_reference - system_before).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
QDeadlineTimer dt_before(system_before, timerType);
QVERIFY2(now > dt_before, QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());

View File

@ -48,6 +48,7 @@ private Q_SLOTS:
void validity(); void validity();
void basics(); void basics();
void elapsed(); void elapsed();
void msecsTo();
}; };
void tst_QElapsedTimer::statics() void tst_QElapsedTimer::statics()
@ -108,30 +109,42 @@ void tst_QElapsedTimer::elapsed()
t1.start(); t1.start();
QTest::qSleep(2*minResolution); 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; QElapsedTimer t2;
t2.start(); t2.start();
QVERIFY(t1 != t2); QVERIFY(t1 != t2);
QVERIFY(!(t1 == t2)); QVERIFY(!(t1 == t2));
QVERIFY(t1 < t2); QVERIFY(t1 < t2);
QVERIFY(t1.msecsTo(t2) > 0);
QVERIFY(t1.nsecsElapsed() > 0); auto diff = t1.msecsTo(t2);
QVERIFY(t1.elapsed() > 0); QVERIFY2(diff > 0, QString("difference t1 and t2 is %1").arg(diff).toLatin1());
// the number of elapsed nanoseconds and milliseconds should match diff = t2.msecsTo(t1);
QVERIFY(t1.nsecsElapsed() - t1.elapsed() * 1000000 < 1000000); QVERIFY2(diff < 0, QString("difference t2 and t1 is %1").arg(diff).toLatin1());
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);
} }
QTEST_MAIN(tst_QElapsedTimer); 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); QVERIFY(list == result);
} }
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
list = str.split(sep, QString::KeepEmptyParts); list = str.split(sep, QString::KeepEmptyParts);
QVERIFY(list == result); QVERIFY(list == result);
list = str.split(rx, QString::KeepEmptyParts); 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); list = str.split(sep.at(0), QString::SkipEmptyParts);
QVERIFY(list == result); QVERIFY(list == result);
} }
QT_WARNING_POP
} }
void tst_QString::split() void tst_QString::split()

View File

@ -1115,6 +1115,12 @@ void tst_QHash::keyValueIterator()
entry_type pair(it.key(), it.value()); entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair); 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; ++key_value_it;
++it; ++it;
} }

View File

@ -881,6 +881,12 @@ void tst_QMap::keyValueIterator()
entry_type pair(it.key(), it.value()); entry_type pair(it.key(), it.value());
QCOMPARE(*key_value_it, pair); 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; ++key_value_it;
++it; ++it;
} }

View File

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